2016-02-28 22:39:55 +01:00
local S = unified_inventory.gettext
-- This pair of encoding functions is used where variable text must go in
-- button names, where the text might contain formspec metacharacters.
-- We can escape button names for the formspec, to avoid screwing up
-- form structure overall, but they then don't get de-escaped, and so
-- the input we get back from the button contains the formspec escaping.
-- This is a game engine bug, and in the anticipation that it might be
-- fixed some day we don't want to rely on it. So for safety we apply
-- an encoding that avoids all formspec metacharacters.
function unified_inventory . mangle_for_formspec ( str )
return string.gsub ( str , " ([^A-Za-z0-9]) " , function ( c ) return string.format ( " _%d_ " , string.byte ( c ) ) end )
end
function unified_inventory . demangle_for_formspec ( str )
return string.gsub ( str , " _([0-9]+)_ " , function ( v ) return string.char ( v ) end )
end
function unified_inventory . get_per_player_formspec ( player_name )
local lite = unified_inventory.lite_mode and not minetest.check_player_privs ( player_name , { ui_full = true } )
local ui = { }
ui.pagecols = unified_inventory.pagecols
ui.pagerows = unified_inventory.pagerows
ui.page_y = unified_inventory.page_y
ui.formspec_y = unified_inventory.formspec_y
ui.main_button_x = unified_inventory.main_button_x
ui.main_button_y = unified_inventory.main_button_y
ui.craft_result_x = unified_inventory.craft_result_x
ui.craft_result_y = unified_inventory.craft_result_y
ui.form_header_y = unified_inventory.form_header_y
if lite then
ui.pagecols = 4
ui.pagerows = 6
ui.page_y = 0.25
ui.formspec_y = 0.47
ui.main_button_x = 8.2
ui.main_button_y = 6.5
ui.craft_result_x = 2.8
ui.craft_result_y = 3.4
ui.form_header_y = - 0.1
end
ui.items_per_page = ui.pagecols * ui.pagerows
return ui , lite
end
function unified_inventory . get_formspec ( player , page )
if not player then
return " "
end
local player_name = player : get_player_name ( )
local ui_peruser , draw_lite_mode = unified_inventory.get_per_player_formspec ( player_name )
unified_inventory.current_page [ player_name ] = page
local pagedef = unified_inventory.pages [ page ]
local formspec = {
" size[14,10] " ,
" background[-0.19,-0.25;14.4,10.75;ui_form_bg.png] " -- Background
}
local n = 3
if draw_lite_mode then
formspec [ 1 ] = " size[11,7.7] "
formspec [ 2 ] = " background[-0.19,-0.2;11.4,8.4;ui_form_bg.png] "
end
if unified_inventory.is_creative ( player_name )
and page == " craft " then
formspec [ n ] = " background[0, " .. ( ui_peruser.formspec_y + 2 ) .. " ;1,1;ui_single_slot.png] "
n = n + 1
end
-- Current page
if not unified_inventory.pages [ page ] then
return " " -- Invalid page name
end
local perplayer_formspec = unified_inventory.get_per_player_formspec ( player_name )
local fsdata = pagedef.get_formspec ( player , perplayer_formspec )
formspec [ n ] = fsdata.formspec
n = n + 1
2016-02-28 22:47:29 +01:00
local privs = minetest.get_player_privs ( player_name ) --Modif MFF (Crabman 13/10/2015) not show if player has not privs requiered
2016-02-28 22:39:55 +01:00
local button_row = 0
local button_col = 0
-- Main buttons
local filtered_inv_buttons = { }
for i , def in pairs ( unified_inventory.buttons ) do
2016-02-28 22:47:29 +01:00
if not ( draw_lite_mode and def.hide_lite ) and ( not def.show_with or ( privs [ def.show_with ] and privs [ def.show_with ] == true ) ) then --Modif MFF (Crabman 13/10/2015) not show if player has not privs requiered
2016-02-28 22:39:55 +01:00
table.insert ( filtered_inv_buttons , def )
end
end
2016-02-28 22:47:29 +01:00
local i = 1 --Modif MFF (Crabman 13/10/2015) 12 buttons max by row
for _ , def in pairs ( filtered_inv_buttons ) do --Modif MFF (Crabman 13/10/2015)
2016-02-28 22:39:55 +01:00
if draw_lite_mode and i > 4 then
button_row = 1
button_col = 1
2016-02-28 22:47:29 +01:00
elseif not draw_lite_mode and i > 12 then --Modif MFF (Crabman 13/10/2015)
button_row = 1
i = 1
2016-02-28 22:39:55 +01:00
end
if def.type == " image " then
formspec [ n ] = " image_button[ "
formspec [ n + 1 ] = ( ui_peruser.main_button_x + 0.65 * ( i - 1 ) - button_col * 0.65 * 4 )
formspec [ n + 2 ] = " , " .. ( ui_peruser.main_button_y + button_row * 0.7 ) .. " ;0.8,0.8; "
formspec [ n + 3 ] = minetest.formspec_escape ( def.image ) .. " ; "
formspec [ n + 4 ] = minetest.formspec_escape ( def.name ) .. " ;] "
formspec [ n + 5 ] = " tooltip[ " .. minetest.formspec_escape ( def.name )
formspec [ n + 6 ] = " ; " .. ( def.tooltip or " " ) .. " ] "
n = n + 7
end
2016-02-28 22:47:29 +01:00
i = i + 1 --Modif MFF (Crabman 13/10/2015)
2016-02-28 22:39:55 +01:00
end
if fsdata.draw_inventory ~= false then
-- Player inventory
formspec [ n ] = " listcolors[#00000000;#00000000] "
formspec [ n + 1 ] = " list[current_player;main;0, " .. ( ui_peruser.formspec_y + 3.5 ) .. " ;8,4;] "
n = n + 2
end
if fsdata.draw_item_list == false then
return table.concat ( formspec , " " )
end
2016-02-28 22:47:29 +01:00
if not unified_inventory.hidden_guide [ player_name ] then --MFF crabman(29/11/2015) hide guide, textfield bug
formspec [ n ] = " image_button[13.2,0.1;.8,.8;ui_on_icon.png;hidebutton;] "
.. " tooltip[hidebutton; " .. S ( " Hide guide " ) .. " ] "
n = n + 1
else
formspec [ n ] = " image_button[13.2,0.1;.8,.8;ui_off_icon.png;hidebutton;] "
.. " tooltip[hidebutton; " .. S ( " Show guide " ) .. " ] "
return table.concat ( formspec , " " )
end
2016-02-28 22:39:55 +01:00
-- Controls to flip items pages
local start_x = 9.2
if not draw_lite_mode then
formspec [ n ] =
" image_button[ " .. ( start_x + 0.6 * 0 )
.. " ,9;.8,.8;ui_skip_backward_icon.png;start_list;] "
.. " tooltip[start_list; " .. minetest.formspec_escape ( S ( " First page " ) ) .. " ] "
.. " image_button[ " .. ( start_x + 0.6 * 1 )
.. " ,9;.8,.8;ui_doubleleft_icon.png;rewind3;] "
.. " tooltip[rewind3; " .. minetest.formspec_escape ( S ( " Back three pages " ) ) .. " ] "
.. " image_button[ " .. ( start_x + 0.6 * 2 )
.. " ,9;.8,.8;ui_left_icon.png;rewind1;] "
.. " tooltip[rewind1; " .. minetest.formspec_escape ( S ( " Back one page " ) ) .. " ] "
.. " image_button[ " .. ( start_x + 0.6 * 3 )
.. " ,9;.8,.8;ui_right_icon.png;forward1;] "
.. " tooltip[forward1; " .. minetest.formspec_escape ( S ( " Forward one page " ) ) .. " ] "
.. " image_button[ " .. ( start_x + 0.6 * 4 )
.. " ,9;.8,.8;ui_doubleright_icon.png;forward3;] "
.. " tooltip[forward3; " .. minetest.formspec_escape ( S ( " Forward three pages " ) ) .. " ] "
.. " image_button[ " .. ( start_x + 0.6 * 5 )
.. " ,9;.8,.8;ui_skip_forward_icon.png;end_list;] "
.. " tooltip[end_list; " .. minetest.formspec_escape ( S ( " Last page " ) ) .. " ] "
else
formspec [ n ] =
" image_button[ " .. ( 8.2 + 0.65 * 0 )
.. " ,5.8;.8,.8;ui_skip_backward_icon.png;start_list;] "
.. " tooltip[start_list; " .. minetest.formspec_escape ( S ( " First page " ) ) .. " ] "
.. " image_button[ " .. ( 8.2 + 0.65 * 1 )
.. " ,5.8;.8,.8;ui_left_icon.png;rewind1;] "
.. " tooltip[rewind1; " .. minetest.formspec_escape ( S ( " Back one page " ) ) .. " ] "
.. " image_button[ " .. ( 8.2 + 0.65 * 2 )
.. " ,5.8;.8,.8;ui_right_icon.png;forward1;] "
.. " tooltip[forward1; " .. minetest.formspec_escape ( S ( " Forward one page " ) ) .. " ] "
.. " image_button[ " .. ( 8.2 + 0.65 * 3 )
.. " ,5.8;.8,.8;ui_skip_forward_icon.png;end_list;] "
.. " tooltip[end_list; " .. minetest.formspec_escape ( S ( " Last page " ) ) .. " ] "
end
n = n + 1
-- Search box
if not draw_lite_mode then
formspec [ n ] = " field[9.5,8.325;3,1;searchbox;; "
.. minetest.formspec_escape ( unified_inventory.current_searchbox [ player_name ] ) .. " ] "
formspec [ n + 1 ] = " image_button[12.2,8.1;.8,.8;ui_search_icon.png;searchbutton;] "
.. " tooltip[searchbutton; " .. S ( " Search " ) .. " ] "
else
formspec [ n ] = " field[8.5,5.225;2.2,1;searchbox;; "
.. minetest.formspec_escape ( unified_inventory.current_searchbox [ player_name ] ) .. " ] "
formspec [ n + 1 ] = " image_button[10.3,5;.8,.8;ui_search_icon.png;searchbutton;] "
.. " tooltip[searchbutton; " .. S ( " Search " ) .. " ] "
end
n = n + 2
local no_matches = " No matching items "
if draw_lite_mode then
no_matches = " No matches. "
end
-- Items list
if # unified_inventory.filtered_items_list [ player_name ] == 0 then
formspec [ n ] = " label[8.2, " .. ui_peruser.form_header_y .. " ; " .. S ( no_matches ) .. " ] "
else
local dir = unified_inventory.active_search_direction [ player_name ]
local list_index = unified_inventory.current_index [ player_name ]
local page = math.floor ( list_index / ( ui_peruser.items_per_page ) + 1 )
local pagemax = math.floor (
( # unified_inventory.filtered_items_list [ player_name ] - 1 )
/ ( ui_peruser.items_per_page ) + 1 )
local item = { }
for y = 0 , ui_peruser.pagerows - 1 do
for x = 0 , ui_peruser.pagecols - 1 do
local name = unified_inventory.filtered_items_list [ player_name ] [ list_index ]
if minetest.registered_items [ name ] then
formspec [ n ] = " item_image_button[ "
.. ( 8.2 + x * 0.7 ) .. " , "
.. ( ui_peruser.formspec_y + ui_peruser.page_y + y * 0.7 ) .. " ;.81,.81; "
.. name .. " ;item_button_ " .. dir .. " _ "
.. unified_inventory.mangle_for_formspec ( name ) .. " ;] "
n = n + 1
list_index = list_index + 1
end
end
end
formspec [ n ] = " label[8.2, " .. ui_peruser.form_header_y .. " ; " .. S ( " Page " ) .. " : "
.. S ( " %s of %s " ) : format ( page , pagemax ) .. " ] "
end
n = n + 1
if unified_inventory.activefilter [ player_name ] ~= " " then
formspec [ n ] = " label[8.2, " .. ( ui_peruser.form_header_y + 0.4 ) .. " ; " .. S ( " Filter " ) .. " :] "
formspec [ n + 1 ] = " label[9.1, " .. ( ui_peruser.form_header_y + 0.4 ) .. " ; " .. minetest.formspec_escape ( unified_inventory.activefilter [ player_name ] ) .. " ] "
end
return table.concat ( formspec , " " )
end
function unified_inventory . set_inventory_formspec ( player , page )
if player then
player : set_inventory_formspec ( unified_inventory.get_formspec ( player , page ) )
end
end
--apply filter to the inventory list (create filtered copy of full one)
function unified_inventory . apply_filter ( player , filter , search_dir )
if not player then
return false
end
local player_name = player : get_player_name ( )
local lfilter = string.lower ( filter )
local ffilter
if lfilter : sub ( 1 , 6 ) == " group: " then
local groups = lfilter : sub ( 7 ) : split ( " , " )
ffilter = function ( name , def )
for _ , group in ipairs ( groups ) do
if not def.groups [ group ]
or def.groups [ group ] <= 0 then
return false
end
end
return true
end
else
ffilter = function ( name , def )
local lname = string.lower ( name )
local ldesc = string.lower ( def.description )
return string.find ( lname , lfilter , 1 , true ) or string.find ( ldesc , lfilter , 1 , true )
end
end
unified_inventory.filtered_items_list [ player_name ] = { }
for name , def in pairs ( minetest.registered_items ) do
if ( not def.groups . not_in_creative_inventory
or def.groups . not_in_creative_inventory == 0 )
and def.description
and def.description ~= " "
and ffilter ( name , def )
and ( unified_inventory.is_creative ( player_name )
or unified_inventory.crafts_for . recipe [ def.name ] ) then
table.insert ( unified_inventory.filtered_items_list [ player_name ] , name )
end
end
table.sort ( unified_inventory.filtered_items_list [ player_name ] )
unified_inventory.filtered_items_list_size [ player_name ] = # unified_inventory.filtered_items_list [ player_name ]
unified_inventory.current_index [ player_name ] = 1
unified_inventory.activefilter [ player_name ] = filter
unified_inventory.active_search_direction [ player_name ] = search_dir
unified_inventory.set_inventory_formspec ( player ,
unified_inventory.current_page [ player_name ] )
end
function unified_inventory . items_in_group ( groups )
local items = { }
for name , item in pairs ( minetest.registered_items ) do
for _ , group in pairs ( groups : split ( ' , ' ) ) do
if item.groups [ group ] then
table.insert ( items , name )
end
end
end
return items
end
function unified_inventory . sort_inventory ( inv )
local inlist = inv : get_list ( " main " )
local typecnt = { }
local typekeys = { }
for _ , st in ipairs ( inlist ) do
if not st : is_empty ( ) then
local n = st : get_name ( )
local w = st : get_wear ( )
local m = st : get_metadata ( )
local k = string.format ( " %s %05d %s " , n , w , m )
if not typecnt [ k ] then
typecnt [ k ] = {
name = n ,
wear = w ,
metadata = m ,
stack_max = st : get_stack_max ( ) ,
count = 0 ,
}
table.insert ( typekeys , k )
end
typecnt [ k ] . count = typecnt [ k ] . count + st : get_count ( )
end
end
table.sort ( typekeys )
local outlist = { }
for _ , k in ipairs ( typekeys ) do
local tc = typecnt [ k ]
while tc.count > 0 do
local c = math.min ( tc.count , tc.stack_max )
table.insert ( outlist , ItemStack ( {
name = tc.name ,
wear = tc.wear ,
metadata = tc.metadata ,
count = c ,
} ) )
tc.count = tc.count - c
end
end
if # outlist > # inlist then return end
while # outlist < # inlist do
table.insert ( outlist , ItemStack ( nil ) )
end
inv : set_list ( " main " , outlist )
end