Add custom compare feature
This commit is contained in:
parent
b25a14188a
commit
87eb35a0ab
13
API.md
13
API.md
@ -7,7 +7,7 @@ to check for the mod's existence first (`minetest.get_modpath`
|
|||||||
returns non-`nil` value).
|
returns non-`nil` value).
|
||||||
|
|
||||||
## Functions
|
## Functions
|
||||||
### `select_item.show_dialog(playername, dialogname, filter)`
|
### `select_item.show_dialog(playername, dialogname, filter, compare)`
|
||||||
Shows an item selection dialog to a player. The player can choose
|
Shows an item selection dialog to a player. The player can choose
|
||||||
one item (which triggers a callback) or abort selection
|
one item (which triggers a callback) or abort selection
|
||||||
(in which case nothing happens).
|
(in which case nothing happens).
|
||||||
@ -21,13 +21,20 @@ to filter out unwanted items.
|
|||||||
#### Parameters
|
#### Parameters
|
||||||
* `playername`: Name of player to show dialog to
|
* `playername`: Name of player to show dialog to
|
||||||
* `dialogname`: Identifier of the dialog (must not contain “%%”)
|
* `dialogname`: Identifier of the dialog (must not contain “%%”)
|
||||||
* `filter`: Optional filter function to narrow down the visible
|
* `filter`: (optional) Filter function to narrow down the visible
|
||||||
items (see below)
|
items (see below)
|
||||||
|
* `compare`: (optional) Custom compare function for sorting,
|
||||||
|
used in `table.sort`.
|
||||||
|
|
||||||
Recommended form of `dialogname` is “`<modname>:<name>`”. Almost all
|
Recommended form of `dialogname` is “`<modname>:<name>`”. Almost all
|
||||||
names are allowed, but they must never contain the substring “%%”.
|
names are allowed, but they must never contain the substring “%%”.
|
||||||
Example: `example:select_my_item`
|
Example: `example:select_my_item`
|
||||||
|
|
||||||
|
Default sorting sorts items alphabetically by itemstring. It
|
||||||
|
moves items with empty description to the end, preceded by items
|
||||||
|
with description, but `not_in_creative_inventory=1`, and then
|
||||||
|
everything else to the beginning.
|
||||||
|
|
||||||
#### Filter function
|
#### Filter function
|
||||||
The filter function has the function signature `filter(itemstring)`.
|
The filter function has the function signature `filter(itemstring)`.
|
||||||
This function will be called for each item with the itemstring
|
This function will be called for each item with the itemstring
|
||||||
|
58
init.lua
58
init.lua
@ -3,11 +3,13 @@ select_item = {}
|
|||||||
-- Cache for result of item filters
|
-- Cache for result of item filters
|
||||||
local player_filters = {}
|
local player_filters = {}
|
||||||
local player_filter_results = {}
|
local player_filter_results = {}
|
||||||
|
local player_compares = {}
|
||||||
local player_maxpage = {}
|
local player_maxpage = {}
|
||||||
|
|
||||||
local reset_player_info = function(playername)
|
local reset_player_info = function(playername)
|
||||||
player_filters[playername] = nil
|
player_filters[playername] = nil
|
||||||
player_filter_results[playername] = nil
|
player_filter_results[playername] = nil
|
||||||
|
player_compares[playername] = nil
|
||||||
player_maxpage[playername] = nil
|
player_maxpage[playername] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -49,33 +51,40 @@ local check_item = function(itemstring, filter)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local get_items = function(filter)
|
local get_items = function(filter, compare)
|
||||||
local it = {}
|
local it = {}
|
||||||
for itemstring, itemdef in pairs(minetest.registered_items) do
|
for itemstring, itemdef in pairs(minetest.registered_items) do
|
||||||
if check_item(itemstring, filter) then
|
if check_item(itemstring, filter) then
|
||||||
table.insert(it, {itemstring=itemstring, itemdef=itemdef})
|
table.insert(it, {itemstring=itemstring, itemdef=itemdef})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Default sorting: Move description-less items and
|
local internal_compare
|
||||||
-- items not_in_creative_inventory=1 to the end, then sort by itemstring.
|
if not compare then
|
||||||
local compare = function(t1, t2)
|
-- Default sorting: Move description-less items and
|
||||||
local t1d = minetest.registered_items[t1.itemstring].description
|
-- items not_in_creative_inventory=1 to the end, then sort by itemstring.
|
||||||
local t2d = minetest.registered_items[t2.itemstring].description
|
internal_compare = function(t1, t2)
|
||||||
local t1g = minetest.get_item_group(t1.itemstring, "not_in_creative_inventory")
|
local t1d = minetest.registered_items[t1.itemstring].description
|
||||||
local t2g = minetest.get_item_group(t2.itemstring, "not_in_creative_inventory")
|
local t2d = minetest.registered_items[t2.itemstring].description
|
||||||
if (t1d == "" and t2d ~= "") then
|
local t1g = minetest.get_item_group(t1.itemstring, "not_in_creative_inventory")
|
||||||
return false
|
local t2g = minetest.get_item_group(t2.itemstring, "not_in_creative_inventory")
|
||||||
elseif (t1d ~= "" and t2d == "") then
|
if (t1d == "" and t2d ~= "") then
|
||||||
return true
|
return false
|
||||||
|
elseif (t1d ~= "" and t2d == "") then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if (t1g == 1 and t2g == 0) then
|
||||||
|
return false
|
||||||
|
elseif (t1g == 0 and t2g == 1) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return t1.itemstring < t2.itemstring
|
||||||
end
|
end
|
||||||
if (t1g == 1 and t2g == 0) then
|
else
|
||||||
return false
|
internal_compare = function(t1, t2)
|
||||||
elseif (t1g == 0 and t2g == 1) then
|
return compare(t1.itemstring, t2.itemstring)
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
return t1.itemstring < t2.itemstring
|
|
||||||
end
|
end
|
||||||
table.sort(it, compare)
|
table.sort(it, internal_compare)
|
||||||
return it
|
return it
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -85,11 +94,12 @@ local ysize_norm = 9
|
|||||||
-- Opens the item selection dialog for player with the given filter function at page.
|
-- Opens the item selection dialog for player with the given filter function at page.
|
||||||
-- The dialog has unique identifier dialogname.
|
-- The dialog has unique identifier dialogname.
|
||||||
-- Returns: Number of items it displays.
|
-- Returns: Number of items it displays.
|
||||||
local show_dialog_page = function(playername, dialogname, filter, page)
|
local show_dialog_page = function(playername, dialogname, filter, compare, page)
|
||||||
local items
|
local items
|
||||||
if player_filters[playername] == nil then
|
if player_filters[playername] == nil then
|
||||||
player_filters[playername] = filter
|
player_filters[playername] = filter
|
||||||
items = get_items(filter)
|
player_compares[playername] = compare
|
||||||
|
items = get_items(filter, compare)
|
||||||
player_filter_results[playername] = items
|
player_filter_results[playername] = items
|
||||||
end
|
end
|
||||||
items = player_filter_results[playername]
|
items = player_filter_results[playername]
|
||||||
@ -151,8 +161,8 @@ local show_dialog_page = function(playername, dialogname, filter, page)
|
|||||||
return #items
|
return #items
|
||||||
end
|
end
|
||||||
|
|
||||||
select_item.show_dialog = function(playername, dialogname, filter)
|
select_item.show_dialog = function(playername, dialogname, filter, compare)
|
||||||
show_dialog_page(playername, dialogname, filter, 1)
|
show_dialog_page(playername, dialogname, filter, compare, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
local callbacks = {}
|
local callbacks = {}
|
||||||
@ -194,11 +204,11 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||||||
end
|
end
|
||||||
if page ~= nil then
|
if page ~= nil then
|
||||||
if fields.previous and page > 1 then
|
if fields.previous and page > 1 then
|
||||||
show_dialog_page(player:get_player_name(), dialogname, player_filters[playername], page - 1)
|
show_dialog_page(player:get_player_name(), dialogname, player_filters[playername], player_compares[playername], page - 1)
|
||||||
elseif fields.next then
|
elseif fields.next then
|
||||||
local maxpage = player_maxpage[playername]
|
local maxpage = player_maxpage[playername]
|
||||||
if maxpage and (page + 1 <= maxpage) then
|
if maxpage and (page + 1 <= maxpage) then
|
||||||
show_dialog_page(playername, dialogname, player_filters[playername], page + 1)
|
show_dialog_page(playername, dialogname, player_filters[playername], player_compares[playername], page + 1)
|
||||||
end
|
end
|
||||||
if not maxpage then
|
if not maxpage then
|
||||||
minetest.log("warning", "[select_item] Player "..playername.." managed to navigate select_item menu without maxpage set!")
|
minetest.log("warning", "[select_item] Player "..playername.." managed to navigate select_item menu without maxpage set!")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user