api.lua 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. sfinv = {
  2. pages = {},
  3. pages_unordered = {},
  4. contexts = {},
  5. enabled = true
  6. }
  7. function sfinv.register_page(name, def)
  8. assert(name, "Invalid sfinv page. Requires a name")
  9. assert(def, "Invalid sfinv page. Requires a def[inition] table")
  10. assert(def.get, "Invalid sfinv page. Def requires a get function.")
  11. assert(not sfinv.pages[name], "Attempt to register already registered sfinv page " .. dump(name))
  12. sfinv.pages[name] = def
  13. def.name = name
  14. table.insert(sfinv.pages_unordered, def)
  15. end
  16. function sfinv.override_page(name, def)
  17. assert(name, "Invalid sfinv page override. Requires a name")
  18. assert(def, "Invalid sfinv page override. Requires a def[inition] table")
  19. local page = sfinv.pages[name]
  20. assert(page, "Attempt to override sfinv page " .. dump(name) .. " which does not exist.")
  21. for key, value in pairs(def) do
  22. page[key] = value
  23. end
  24. end
  25. function sfinv.get_nav_fs(player, context, nav, current_idx)
  26. -- Only show tabs if there is more than one page
  27. if #nav > 1 then
  28. return "tabheader[0,0;sfinv_nav_tabs;" .. table.concat(nav, ",") ..
  29. ";" .. current_idx .. ";true;false]"..
  30. "image[-.5,-.3;11,.1;sfinv_underline.png]"
  31. else
  32. return ""
  33. end
  34. end
  35. local theme_inv = [[
  36. image[0,5.2;1,1;gui_hb_bg.png]
  37. image[1,5.2;1,1;gui_hb_bg.png]
  38. image[2,5.2;1,1;gui_hb_bg.png]
  39. image[3,5.2;1,1;gui_hb_bg.png]
  40. image[4,5.2;1,1;gui_hb_bg.png]
  41. image[5,5.2;1,1;gui_hb_bg.png]
  42. image[6,5.2;1,1;gui_hb_bg.png]
  43. image[7,5.2;1,1;gui_hb_bg.png]
  44. list[current_player;main;0,5.2;8,1;]
  45. list[current_player;main;0,6.35;8,3;8]
  46. ]]
  47. function sfinv.make_formspec(player, context, content, show_inv, size)
  48. local tmp = {
  49. size or "size[8,9.1]",
  50. "background9[-2,-2;12,13.1;sfinv_bg.png;false;64,96]",
  51. sfinv.get_nav_fs(player, context, context.nav_titles, context.nav_idx),
  52. show_inv and theme_inv or "",
  53. content
  54. }
  55. return table.concat(tmp, "")
  56. end
  57. function sfinv.get_homepage_name(player)
  58. return "sfinv:crafting"
  59. end
  60. function sfinv.get_formspec(player, context)
  61. -- Generate navigation tabs
  62. local nav = {}
  63. local nav_ids = {}
  64. local current_idx = 1
  65. for i, pdef in pairs(sfinv.pages_unordered) do
  66. if not pdef.is_in_nav or pdef:is_in_nav(player, context) then
  67. nav[#nav + 1] = pdef.title
  68. nav_ids[#nav_ids + 1] = pdef.name
  69. if pdef.name == context.page then
  70. current_idx = #nav_ids
  71. end
  72. end
  73. end
  74. context.nav = nav_ids
  75. context.nav_titles = nav
  76. context.nav_idx = current_idx
  77. -- Generate formspec
  78. local page = sfinv.pages[context.page] or sfinv.pages["404"]
  79. if page then
  80. return page:get(player, context)
  81. else
  82. local old_page = context.page
  83. local home_page = sfinv.get_homepage_name(player)
  84. if old_page == home_page then
  85. minetest.log("error", "[sfinv] Couldn't find " .. dump(old_page) ..
  86. ", which is also the old page")
  87. return ""
  88. end
  89. context.page = home_page
  90. assert(sfinv.pages[context.page], "[sfinv] Invalid homepage")
  91. minetest.log("warning", "[sfinv] Couldn't find " .. dump(old_page) ..
  92. " so switching to homepage")
  93. return sfinv.get_formspec(player, context)
  94. end
  95. end
  96. function sfinv.get_or_create_context(player)
  97. local name = player:get_player_name()
  98. local context = sfinv.contexts[name]
  99. if not context then
  100. context = {
  101. page = sfinv.get_homepage_name(player)
  102. }
  103. sfinv.contexts[name] = context
  104. end
  105. return context
  106. end
  107. function sfinv.set_context(player, context)
  108. sfinv.contexts[player:get_player_name()] = context
  109. end
  110. function sfinv.set_player_inventory_formspec(player, context)
  111. local fs = sfinv.get_formspec(player,
  112. context or sfinv.get_or_create_context(player))
  113. player:set_inventory_formspec(fs)
  114. end
  115. function sfinv.set_page(player, pagename)
  116. local context = sfinv.get_or_create_context(player)
  117. local oldpage = sfinv.pages[context.page]
  118. if oldpage and oldpage.on_leave then
  119. oldpage:on_leave(player, context)
  120. end
  121. context.page = pagename
  122. local page = sfinv.pages[pagename]
  123. if page.on_enter then
  124. page:on_enter(player, context)
  125. end
  126. sfinv.set_player_inventory_formspec(player, context)
  127. end
  128. function sfinv.get_page(player)
  129. local context = sfinv.contexts[player:get_player_name()]
  130. return context and context.page or sfinv.get_homepage_name(player)
  131. end
  132. minetest.register_on_joinplayer(function(player)
  133. if sfinv.enabled then
  134. sfinv.set_player_inventory_formspec(player)
  135. end
  136. end)
  137. minetest.register_on_leaveplayer(function(player)
  138. sfinv.contexts[player:get_player_name()] = nil
  139. end)
  140. minetest.register_on_player_receive_fields(function(player, formname, fields)
  141. if formname ~= "" or not sfinv.enabled then
  142. return false
  143. end
  144. -- Get Context
  145. local name = player:get_player_name()
  146. local context = sfinv.contexts[name]
  147. if not context then
  148. sfinv.set_player_inventory_formspec(player)
  149. return false
  150. end
  151. -- Was a tab selected?
  152. if fields.sfinv_nav_tabs and context.nav then
  153. local tid = tonumber(fields.sfinv_nav_tabs)
  154. if tid and tid > 0 then
  155. local id = context.nav[tid]
  156. local page = sfinv.pages[id]
  157. if id and page then
  158. sfinv.set_page(player, id)
  159. end
  160. end
  161. else
  162. -- Pass event to page
  163. local page = sfinv.pages[context.page]
  164. if page and page.on_player_receive_fields then
  165. return page:on_player_receive_fields(player, context, fields)
  166. end
  167. end
  168. end)