craftingtool.lua 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. local MP = minetest.get_modpath(minetest.get_current_modname())
  2. local S, NS = dofile(MP.."/intllib.lua")
  3. local modpath_default = minetest.get_modpath("default")
  4. --TODO: currently, this acts as useful inventory storage space in addition to crafting. Would be nice to do something about that, perhaps making the "input" inventory illusory. Will require modification to the "craft_stack" method or perhaps a variant on it.
  5. -- table_def can have the following:
  6. --{
  7. -- show_guides = true or false,
  8. -- alphabetize_items = true or false,
  9. -- description = string,
  10. -- append_to_formspec = string,
  11. --}
  12. simplecrafting_lib.player_contexts = simplecrafting_lib.player_contexts or {}
  13. simplecrafting_lib.generate_tool_functions = function(craft_type, table_def)
  14. if table_def == nil then
  15. table_def = {}
  16. end
  17. local output_width = 8
  18. local output_height = 6
  19. local output_count = output_width * output_height
  20. local function refresh_output(inv, max_mode)
  21. local craftable = simplecrafting_lib.get_craftable_items(craft_type, inv:get_list(craft_type.."_input"), max_mode, table_def.alphabetize_items)
  22. inv:set_size(craft_type.."_output", #craftable + (output_count - (#craftable%output_count)))
  23. inv:set_list(craft_type.."_output", craftable)
  24. end
  25. local function make_formspec(row, item_count, max_mode)
  26. if item_count < output_count then
  27. row = 0
  28. elseif (row*output_width)+output_count > item_count then
  29. row = (item_count - output_count) / output_width
  30. end
  31. local inventory = {
  32. "size[10.2,10.2]",
  33. "list[current_player;"..craft_type.."_input;0,0.5;2,5;]",
  34. "list[current_player;"..craft_type.."_output;2.2,0;"..output_width..","..output_height..";" , tostring(row*output_width), "]",
  35. "list[current_player;main;1.1,6.25;8,1;]",
  36. "list[current_player;main;1.1,7.5;8,3;8]",
  37. "listring[current_player;"..craft_type.."_output]",
  38. "listring[current_player;main]",
  39. "listring[current_player;"..craft_type.."_input]",
  40. "listring[current_player;main]",
  41. }
  42. if table_def.description then
  43. inventory[#inventory+1] = "label[0,0;"..table_def.description.."]"
  44. end
  45. if modpath_default then
  46. inventory[#inventory+1] = default.gui_bg
  47. inventory[#inventory+1] = default.gui_bg_img
  48. inventory[#inventory+1] = default.gui_slots
  49. end
  50. local pages = false
  51. local page_button_y = "7.3"
  52. if item_count > ((row/output_height)+1) * output_count then
  53. inventory[#inventory+1] = "button[9.3,"..page_button_y..";1,0.75;next;»]"
  54. inventory[#inventory+1] = "tooltip[next;"..S("Next page of crafting products").."]"
  55. page_button_y = "8.0"
  56. pages = true
  57. end
  58. if row >= output_height then
  59. inventory[#inventory+1] = "button[9.3,"..page_button_y..";1,0.75;prev;«]"
  60. inventory[#inventory+1] = "tooltip[prev;"..S("Previous page of crafting products").."]"
  61. pages = true
  62. end
  63. if pages then
  64. inventory[#inventory+1] = "label[9.3,6.5;" .. S("Page @1", tostring(row/output_height+1)) .. "]"
  65. end
  66. if max_mode then
  67. inventory[#inventory+1] = "button[9.3,8.7;1,0.75;max_mode;"..S("Max\nOutput").."]"
  68. else
  69. inventory[#inventory+1] = "button[9.3,8.7;1,0.75;max_mode;"..S("Min\nOutput").."]"
  70. end
  71. if table_def.show_guides then
  72. inventory[#inventory+1] = "button[9.3,9.7;1,0.75;show_guide;"..S("Show\nGuide").."]"
  73. end
  74. if table_def.append_to_formspec then
  75. inventory[#inventory+1] = table_def.append_to_formspec
  76. end
  77. return table.concat(inventory), row
  78. end
  79. local get_or_create_context = function(player)
  80. local name = player:get_player_name()
  81. local context = simplecrafting_lib.player_contexts[name]
  82. if not context then
  83. context = {row = 0, formspec = make_formspec(0, 0, true)}
  84. simplecrafting_lib.player_contexts[name] = context
  85. end
  86. return context
  87. end
  88. minetest.register_on_joinplayer(function(player)
  89. local inv = minetest.get_inventory({type="player", name=player:get_player_name()})
  90. inv:set_size(craft_type.."_input", 2*5)
  91. inv:set_size(craft_type.."_output", output_count)
  92. end)
  93. minetest.register_on_leaveplayer(function(player)
  94. simplecrafting_lib.player_contexts[player:get_player_name()] = nil
  95. end)
  96. local function refresh_inv(inv, player)
  97. local context = get_or_create_context(player)
  98. local max_mode = context.max_mode
  99. refresh_output(inv, max_mode)
  100. local row = context.row
  101. local form, row = make_formspec(row, inv:get_size(craft_type.."_output"), max_mode)
  102. context.row = row
  103. context.formspec = form
  104. minetest.show_formspec(player:get_player_name(),
  105. "simplecrafting_lib:tool:"..craft_type,
  106. context.formspec)
  107. end
  108. minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info)
  109. if action == "move" then
  110. if inventory_info.to_list == craft_type.."_output" then
  111. return 0
  112. end
  113. if inventory_info.to_list == craft_type.."_input" then
  114. if inventory_info.from_list == craft_type.."_input" then
  115. return inventory_info.count
  116. end
  117. local stack = inventory:get_stack(inventory_info.from_list, inventory_info.from_index)
  118. if simplecrafting_lib.is_possible_input(craft_type, stack:get_name()) then
  119. return inventory_info.count
  120. end
  121. end
  122. if inventory_info.to_list == "main" then
  123. return inventory_info.count
  124. end
  125. end
  126. end)
  127. minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info)
  128. if action == "move" then
  129. local from_output = inventory_info.from_list == craft_type.."_output"
  130. local to_input = inventory_info.to_list == craft_type.."_input"
  131. if from_output and (to_input or inventory_info.to_list == "main") then
  132. local stack = inventory:get_stack(inventory_info.to_list, inventory_info.to_index)
  133. stack:set_count(inventory_info.count)
  134. simplecrafting_lib.craft_stack(craft_type, stack, inventory, craft_type.."_input", inventory, inventory_info.to_list, player)
  135. if simplecrafting_lib.award_crafting then
  136. simplecrafting_lib.award_crafting(player, stack)
  137. end
  138. end
  139. if from_output or to_input or inventory_info.from_list == craft_type.."_input" then
  140. refresh_inv(inventory, player)
  141. end
  142. end
  143. end)
  144. minetest.register_on_player_receive_fields(function(player, formname, fields)
  145. if string.sub(formname, 1, 24) ~= "simplecrafting_lib:tool:" then return false end
  146. if string.sub(formname, 25) ~= craft_type then return false end
  147. local inv = minetest.get_inventory({type="player", name=player:get_player_name()})
  148. local context = get_or_create_context(player)
  149. local size = inv:get_size(craft_type.."_output")
  150. local row = context.row
  151. local refresh = false
  152. if fields.next then
  153. minetest.sound_play("paperflip1", {to_player=player:get_player_name(), gain = 1.0})
  154. row = row + output_height
  155. elseif fields.prev then
  156. minetest.sound_play("paperflip2", {to_player=player:get_player_name(), gain = 1.0})
  157. row = row - output_height
  158. elseif fields.max_mode then
  159. context.max_mode = not context.max_mode
  160. refresh = true
  161. elseif fields.show_guide and table_def.show_guides then
  162. simplecrafting_lib.show_crafting_guide(craft_type, player,
  163. function()
  164. minetest.after(0.1, function()
  165. minetest.show_formspec(player:get_player_name(), formname, context.formspec)
  166. end)
  167. end
  168. )
  169. else
  170. return
  171. end
  172. context.row = row
  173. if refresh then
  174. refresh_inv(inv, player)
  175. end
  176. end)
  177. return function(player)
  178. local context = get_or_create_context(player)
  179. minetest.show_formspec(player:get_player_name(),
  180. "simplecrafting_lib:"..craft_type,
  181. context.formspec)
  182. end
  183. end