api.lua 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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;tabs;" .. table.concat(nav, ",") .. ";" .. current_idx .. ";true;false]"
  29. else
  30. return ""
  31. end
  32. end
  33. local theme_main = "bgcolor[#080808BB;true]" .. default.gui_bg ..
  34. default.gui_bg_img
  35. local theme_inv = default.gui_slots .. [[
  36. list[current_player;main;0,4.7;8,1;]
  37. list[current_player;main;0,5.85;8,3;8]
  38. ]]
  39. function sfinv.make_formspec(player, context, content, show_inv, size)
  40. local tmp = {
  41. size or "size[8,8.6]",
  42. theme_main,
  43. sfinv.get_nav_fs(player, context, context.nav_titles, context.nav_idx),
  44. content
  45. }
  46. if show_inv then
  47. tmp[#tmp + 1] = theme_inv
  48. end
  49. return table.concat(tmp, "")
  50. end
  51. function sfinv.get_homepage_name(player)
  52. return "sfinv:crafting"
  53. end
  54. function sfinv.get_formspec(player, context)
  55. -- Generate navigation tabs
  56. local nav = {}
  57. local nav_ids = {}
  58. local current_idx = 1
  59. for i, pdef in pairs(sfinv.pages_unordered) do
  60. if not pdef.is_in_nav or pdef:is_in_nav(player, context) then
  61. nav[#nav + 1] = pdef.title
  62. nav_ids[#nav_ids + 1] = pdef.name
  63. if pdef.name == context.page then
  64. current_idx = #nav_ids
  65. end
  66. end
  67. end
  68. context.nav = nav_ids
  69. context.nav_titles = nav
  70. context.nav_idx = current_idx
  71. -- Generate formspec
  72. local page = sfinv.pages[context.page] or sfinv.pages["404"]
  73. if page then
  74. return page:get(player, context)
  75. else
  76. local old_page = context.page
  77. context.page = sfinv.get_homepage_name(player)
  78. assert(sfinv.pages[context.page], "[sfinv] Invalid homepage")
  79. minetest.log("warning", "[sfinv] Couldn't find " .. dump(old_page) .. " so using switching to homepage")
  80. return sfinv.get_formspec(player, context)
  81. end
  82. end
  83. function sfinv.get_or_create_context(player)
  84. local name = player:get_player_name()
  85. local context = sfinv.contexts[name]
  86. if not context then
  87. context = {
  88. page = sfinv.get_homepage_name(player)
  89. }
  90. sfinv.contexts[name] = context
  91. end
  92. return context
  93. end
  94. function sfinv.set_context(player, context)
  95. sfinv.contexts[player:get_player_name()] = context
  96. end
  97. function sfinv.set_player_inventory_formspec(player, context)
  98. local fs = sfinv.get_formspec(player,
  99. context or sfinv.get_or_create_context(player))
  100. player:set_inventory_formspec(fs)
  101. end
  102. function sfinv.set_page(player, pagename)
  103. local context = sfinv.get_or_create_context(player)
  104. local oldpage = sfinv.pages[context.page]
  105. if oldpage and oldpage.on_leave then
  106. oldpage:on_leave(player, context)
  107. end
  108. context.page = pagename
  109. local page = sfinv.pages[pagename]
  110. if page.on_enter then
  111. page:on_enter(player, context)
  112. end
  113. sfinv.set_player_inventory_formspec(player, context)
  114. end
  115. minetest.register_on_joinplayer(function(player)
  116. if sfinv.enabled then
  117. sfinv.set_player_inventory_formspec(player)
  118. end
  119. end)
  120. minetest.register_on_leaveplayer(function(player)
  121. sfinv.contexts[player:get_player_name()] = nil
  122. end)
  123. minetest.register_on_player_receive_fields(function(player, formname, fields)
  124. if formname ~= "" or not sfinv.enabled then
  125. return false
  126. end
  127. -- Get Context
  128. local name = player:get_player_name()
  129. local context = sfinv.contexts[name]
  130. if not context then
  131. sfinv.set_player_inventory_formspec(player)
  132. return false
  133. end
  134. -- Was a tab selected?
  135. if fields.tabs and context.nav then
  136. local tid = tonumber(fields.tabs)
  137. if tid and tid > 0 then
  138. local id = context.nav[tid]
  139. local page = sfinv.pages[id]
  140. if id and page then
  141. sfinv.set_page(player, id)
  142. end
  143. end
  144. else
  145. -- Pass event to page
  146. local page = sfinv.pages[context.page]
  147. if page and page.on_player_receive_fields then
  148. return page:on_player_receive_fields(player, context, fields)
  149. end
  150. end
  151. end)