inventory.lua 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. local player_inventory = {}
  2. local inventory_cache = {}
  3. local function init_creative_cache(items)
  4. inventory_cache[items] = {}
  5. local i_cache = inventory_cache[items]
  6. for name, def in pairs(items) do
  7. if def.groups.not_in_creative_inventory ~= 1 and
  8. def.description and def.description ~= "" then
  9. i_cache[name] = def
  10. end
  11. end
  12. table.sort(i_cache)
  13. return i_cache
  14. end
  15. function creative.init_creative_inventory(player)
  16. local player_name = player:get_player_name()
  17. player_inventory[player_name] = {
  18. size = 0,
  19. filter = "",
  20. start_i = 0
  21. }
  22. minetest.create_detached_inventory("creative_" .. player_name, {
  23. allow_move = function(inv, from_list, from_index, to_list, to_index, count, player2)
  24. local name = player2 and player2:get_player_name() or ""
  25. if not creative.is_enabled_for(name) or
  26. to_list == "main" then
  27. return 0
  28. end
  29. return count
  30. end,
  31. allow_put = function(inv, listname, index, stack, player2)
  32. return 0
  33. end,
  34. allow_take = function(inv, listname, index, stack, player2)
  35. local name = player2 and player2:get_player_name() or ""
  36. if not creative.is_enabled_for(name) then
  37. return 0
  38. end
  39. return -1
  40. end,
  41. on_move = function(inv, from_list, from_index, to_list, to_index, count, player2)
  42. end,
  43. on_take = function(inv, listname, index, stack, player2)
  44. if stack and stack:get_count() > 0 then
  45. minetest.log("action", player_name .. " takes " .. stack:get_name().. " from creative inventory")
  46. end
  47. end,
  48. }, player_name)
  49. return player_inventory[player_name]
  50. end
  51. function creative.update_creative_inventory(player_name, tab_content)
  52. local creative_list = {}
  53. local inv = player_inventory[player_name] or
  54. creative.init_creative_inventory(minetest.get_player_by_name(player_name))
  55. local player_inv = minetest.get_inventory({type = "detached", name = "creative_" .. player_name})
  56. local items = inventory_cache[tab_content] or init_creative_cache(tab_content)
  57. for name, def in pairs(items) do
  58. if def.name:find(inv.filter, 1, true) or
  59. def.description:lower():find(inv.filter, 1, true) then
  60. creative_list[#creative_list+1] = name
  61. end
  62. end
  63. table.sort(creative_list)
  64. player_inv:set_size("main", #creative_list)
  65. player_inv:set_list("main", creative_list)
  66. inv.size = #creative_list
  67. end
  68. -- Create the trash field
  69. local trash = minetest.create_detached_inventory("creative_trash", {
  70. -- Allow the stack to be placed and remove it in on_put()
  71. -- This allows the creative inventory to restore the stack
  72. allow_put = function(inv, listname, index, stack, player)
  73. return stack:get_count()
  74. end,
  75. on_put = function(inv, listname)
  76. inv:set_list(listname, {})
  77. end,
  78. })
  79. trash:set_size("main", 1)
  80. creative.formspec_add = ""
  81. function creative.register_tab(name, title, items)
  82. sfinv.register_page("creative:" .. name, {
  83. title = title,
  84. is_in_nav = function(self, player, context)
  85. return creative.is_enabled_for(player:get_player_name())
  86. end,
  87. get = function(self, player, context)
  88. local player_name = player:get_player_name()
  89. creative.update_creative_inventory(player_name, items)
  90. local inv = player_inventory[player_name]
  91. local start_i = inv.start_i or 0
  92. local pagenum = math.floor(start_i / (3*8) + 1)
  93. local pagemax = math.ceil(inv.size / (3*8))
  94. return sfinv.make_formspec(player, context,
  95. "label[6.2,3.35;" .. minetest.colorize("#FFFF00", tostring(pagenum)) .. " / " .. tostring(pagemax) .. "]" ..
  96. [[
  97. image[4.06,3.4;0.8,0.8;creative_trash_icon.png]
  98. listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]
  99. list[current_player;main;0,4.7;8,1;]
  100. list[current_player;main;0,5.85;8,3;8]
  101. list[detached:creative_trash;main;4,3.3;1,1;]
  102. listring[]
  103. image_button[5.4,3.25;0.8,0.8;creative_prev_icon.png;creative_prev;]
  104. image_button[7.2,3.25;0.8,0.8;creative_next_icon.png;creative_next;]
  105. image_button[2.1,3.25;0.8,0.8;creative_search_icon.png;creative_search;]
  106. image_button[2.75,3.25;0.8,0.8;creative_clear_icon.png;creative_clear;]
  107. tooltip[creative_search;Search]
  108. tooltip[creative_clear;Reset]
  109. tooltip[creative_prev;Previous page]
  110. tooltip[creative_next;Next page]
  111. listring[current_player;main]
  112. field_close_on_enter[creative_filter;false]
  113. ]] ..
  114. "field[0.3,3.5;2.2,1;creative_filter;;" .. minetest.formspec_escape(inv.filter) .. "]" ..
  115. "listring[detached:creative_" .. player_name .. ";main]" ..
  116. "list[detached:creative_" .. player_name .. ";main;0,0;8,3;" .. tostring(start_i) .. "]" ..
  117. default.get_hotbar_bg(0,4.7) ..
  118. default.gui_bg .. default.gui_bg_img .. default.gui_slots
  119. .. creative.formspec_add, false)
  120. end,
  121. on_enter = function(self, player, context)
  122. local player_name = player:get_player_name()
  123. local inv = player_inventory[player_name]
  124. if inv then
  125. inv.start_i = 0
  126. end
  127. end,
  128. on_player_receive_fields = function(self, player, context, fields)
  129. local player_name = player:get_player_name()
  130. local inv = player_inventory[player_name]
  131. assert(inv)
  132. if fields.creative_clear then
  133. inv.start_i = 0
  134. inv.filter = ""
  135. creative.update_creative_inventory(player_name, items)
  136. sfinv.set_player_inventory_formspec(player, context)
  137. elseif fields.creative_search or
  138. fields.key_enter_field == "creative_filter" then
  139. inv.start_i = 0
  140. inv.filter = fields.creative_filter:lower()
  141. creative.update_creative_inventory(player_name, items)
  142. sfinv.set_player_inventory_formspec(player, context)
  143. elseif not fields.quit then
  144. local start_i = inv.start_i or 0
  145. if fields.creative_prev then
  146. start_i = start_i - 3*8
  147. if start_i < 0 then
  148. start_i = inv.size - (inv.size % (3*8))
  149. if inv.size == start_i then
  150. start_i = math.max(0, inv.size - (3*8))
  151. end
  152. end
  153. elseif fields.creative_next then
  154. start_i = start_i + 3*8
  155. if start_i >= inv.size then
  156. start_i = 0
  157. end
  158. end
  159. inv.start_i = start_i
  160. sfinv.set_player_inventory_formspec(player, context)
  161. end
  162. end
  163. })
  164. end
  165. creative.register_tab("all", "All", minetest.registered_items)
  166. creative.register_tab("nodes", "Nodes", minetest.registered_nodes)
  167. creative.register_tab("tools", "Tools", minetest.registered_tools)
  168. creative.register_tab("craftitems", "Items", minetest.registered_craftitems)
  169. local old_homepage_name = sfinv.get_homepage_name
  170. function sfinv.get_homepage_name(player)
  171. if creative.is_enabled_for(player:get_player_name()) then
  172. return "creative:all"
  173. else
  174. return old_homepage_name(player)
  175. end
  176. end