utility.lua 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. -- internationalization boilerplate
  2. local MP = minetest.get_modpath(minetest.get_current_modname())
  3. local S, NS = dofile(MP.."/intllib.lua")
  4. -- Target inventory retrieval
  5. -- looks first for a registration matching the specific node name, then for a registration
  6. -- matching group and value, then for a registration matching a group and *any* value
  7. hopper.get_registered_inventories_for = function(target_node_name)
  8. local output = hopper.containers[target_node_name]
  9. if output ~= nil then return output end
  10. local target_def = minetest.registered_nodes[target_node_name]
  11. if target_def == nil or target_def.groups == nil then return nil end
  12. for group, value in pairs(target_def.groups) do
  13. local registered_group = hopper.groups[group]
  14. if registered_group ~= nil then
  15. output = registered_group[value]
  16. if output ~= nil then return output end
  17. output = registered_group["all"]
  18. if output ~= nil then return output end
  19. end
  20. end
  21. return nil
  22. end
  23. hopper.get_eject_button_texts = function(pos, loc_X, loc_Y)
  24. if not hopper.config.eject_button_enabled then return "" end
  25. local eject_button_text, eject_button_tooltip
  26. if minetest.get_meta(pos):get_string("eject") == "true" then
  27. eject_button_text = S("Don't\nEject")
  28. eject_button_tooltip = S("This hopper is currently set to eject items from its output\neven if there isn't a compatible block positioned to receive it.\nClick this button to disable this feature.")
  29. local timer1 = minetest.get_node_timer(pos)
  30. if not timer1:is_started() then
  31. timer1:start(1.0)
  32. end
  33. else
  34. eject_button_text = S("Eject\nItems")
  35. eject_button_tooltip = S("This hopper is currently set to hold on to item if there\nisn't a compatible block positioned to receive it.\nClick this button to have it eject items instead.")
  36. local timer1 = minetest.get_node_timer(pos)
  37. if not timer1:is_started() then
  38. timer1:start(1.0)
  39. end
  40. end
  41. return "button_exit["..loc_X..","..loc_Y..";1,1;eject;"..eject_button_text.."]tooltip[eject;"..eject_button_tooltip.."]"
  42. end
  43. hopper.get_string_pos = function(pos)
  44. return pos.x .. "," .. pos.y .. "," ..pos.z
  45. end
  46. -- Apparently node_sound_metal_defaults is a newer thing, I ran into games using an older version of the default mod without it.
  47. if default.node_sound_metal_defaults ~= nil then
  48. hopper.metal_sounds = default.node_sound_metal_defaults()
  49. else
  50. hopper.metal_sounds = default.node_sound_stone_defaults()
  51. end
  52. -------------------------------------------------------------------------------------------
  53. -- Inventory transfer functions
  54. local delay = function(x)
  55. return (function() return x end)
  56. end
  57. local get_placer = function(player_name)
  58. if player_name ~= "" then
  59. return minetest.get_player_by_name(player_name) or {
  60. is_player = delay(true),
  61. get_player_name = delay(player_name),
  62. is_fake_player = ":hopper",
  63. get_wielded_item = delay(ItemStack(nil))
  64. }
  65. end
  66. return nil
  67. end
  68. -- Used to remove items from the target block and put it into the hopper's inventory
  69. hopper.take_item_from = function(hopper_pos, target_pos, target_node, target_inventory_name)
  70. if target_inventory_name == nil then
  71. return
  72. end
  73. local target_def = minetest.registered_nodes[target_node.name]
  74. if not target_def then
  75. return
  76. end
  77. --hopper inventory
  78. local hopper_meta = minetest.get_meta(hopper_pos);
  79. local hopper_inv = hopper_meta:get_inventory()
  80. local placer = get_placer(hopper_meta:get_string("placer"))
  81. --source inventory
  82. local target_inv = minetest.get_meta(target_pos):get_inventory()
  83. local target_inv_size = target_inv:get_size(target_inventory_name)
  84. if target_inv:is_empty(target_inventory_name) == false then
  85. for i = 1,target_inv_size do
  86. local stack = target_inv:get_stack(target_inventory_name, i)
  87. local item = stack:get_name()
  88. if item ~= "" then
  89. if hopper_inv:room_for_item("main", item) then
  90. local stack_to_take = stack:take_item(1)
  91. if target_def.allow_metadata_inventory_take == nil
  92. or placer == nil -- backwards compatibility, older versions of this mod didn't record who placed the hopper
  93. or target_def.allow_metadata_inventory_take(target_pos, target_inventory_name, i, stack_to_take, placer) > 0 then
  94. target_inv:set_stack(target_inventory_name, i, stack)
  95. --add to hopper
  96. hopper_inv:add_item("main", stack_to_take)
  97. if target_def.on_metadata_inventory_take ~= nil and placer ~= nil then
  98. target_def.on_metadata_inventory_take(target_pos, target_inventory_name, i, stack_to_take, placer)
  99. end
  100. break
  101. end
  102. end
  103. end
  104. end
  105. local timer1 = minetest.get_node_timer(hopper_pos)
  106. if not timer1:is_started() then
  107. timer1:start(1.0)
  108. end
  109. local timer2 = minetest.get_node_timer(target_pos)
  110. if not timer2:is_started() then
  111. timer2:start(1.0)
  112. end
  113. end
  114. end
  115. -- Used to put items from the hopper inventory into the target block
  116. hopper.send_item_to = function(hopper_pos, target_pos, target_node, target_inventory_name, filtered_items)
  117. local hopper_meta = minetest.get_meta(hopper_pos)
  118. local target_def = minetest.registered_nodes[target_node.name]
  119. if not target_def then
  120. return false
  121. end
  122. local eject_item = hopper.config.eject_button_enabled and hopper_meta:get_string("eject") == "true" and target_def.buildable_to
  123. if not eject_item and not target_inventory_name then
  124. return false
  125. end
  126. --hopper inventory
  127. local hopper_meta = minetest.get_meta(hopper_pos);
  128. local hopper_inv = hopper_meta:get_inventory()
  129. if hopper_inv:is_empty("main") == true then
  130. return false
  131. end
  132. local hopper_inv_size = hopper_inv:get_size("main")
  133. local placer = get_placer(hopper_meta:get_string("placer"))
  134. --target inventory
  135. local target_inv = minetest.get_meta(target_pos):get_inventory()
  136. for i = 1,hopper_inv_size do
  137. local stack = hopper_inv:get_stack("main", i)
  138. local item = stack:get_name()
  139. if item ~= "" and (filtered_items == nil or filtered_items[item]) then
  140. if target_inventory_name then
  141. if target_inv:room_for_item(target_inventory_name, item) then
  142. local stack_to_put = stack:take_item(1)
  143. if target_def.allow_metadata_inventory_put == nil
  144. or placer == nil -- backwards compatibility, older versions of this mod didn't record who placed the hopper
  145. or target_def.allow_metadata_inventory_put(target_pos, target_inventory_name, i, stack_to_put, placer) > 0 then
  146. hopper_inv:set_stack("main", i, stack)
  147. --add to target node
  148. target_inv:add_item(target_inventory_name, stack_to_put)
  149. if target_def.on_metadata_inventory_put ~= nil and placer ~= nil then
  150. target_def.on_metadata_inventory_put(target_pos, target_inventory_name, i, stack_to_put, placer)
  151. end
  152. local timer1 = minetest.get_node_timer(hopper_pos)
  153. if not timer1:is_started() then
  154. timer1:start(1.0)
  155. end
  156. local timer2 = minetest.get_node_timer(target_pos)
  157. if not timer2:is_started() then
  158. timer2:start(1.0)
  159. end
  160. return true
  161. end
  162. end
  163. elseif eject_item then
  164. local stack_to_put = stack:take_item(1)
  165. minetest.add_item(target_pos, stack_to_put)
  166. hopper_inv:set_stack("main", i, stack)
  167. local timer1 = minetest.get_node_timer(hopper_pos)
  168. if not timer1:is_started() then
  169. timer1:start(1.0)
  170. end
  171. local timer2 = minetest.get_node_timer(target_pos)
  172. if not timer2:is_started() then
  173. timer2:start(1.0)
  174. end
  175. return true
  176. end
  177. end
  178. end
  179. return false
  180. end