harvester.lua 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. -- EDITED BY HarrierJack
  2. -- fixed syntax + spelling errors
  3. -- fixed old texture references
  4. -- borrowed function from technic
  5. local S = technic.getter
  6. -- get some vars from gobal settings cause I was too lazy to change calculation references
  7. -- local harvester_dig_above_nodes = autofarmer.MV_harvester_max_height
  8. local harvester_max_depth = autofarmer.MV_harvester_max_depth
  9. local function get_label(meta)
  10. if meta:get_int("enabled") == 1 then
  11. return "Disable"
  12. else return "Enable" end
  13. end
  14. local function get_harvester_formspec(side, length, height, label)
  15. return "size[3,3]"..
  16. "field[0.3,0.5;1,1;side;Side;"..side.."]"..
  17. "field[1.3,0.5;1,1;length;Length;"..length.."]"..
  18. "field[2.3,0.5;1,1;height;Height;"..height.."]"..
  19. "button[0.5,1;2,1;toggle;"..label.."]"..
  20. "button_exit[1,2;1,1;exit;Save]"
  21. end
  22. local function harvester_receive_fields(pos, formname, fields, sender)
  23. local meta = minetest.get_meta(pos)
  24. if fields.side and fields.length and fields.height then
  25. -- check side/length values
  26. if string.find(fields.side, "^[0-9]+$") and string.find(fields.length, "^[0-9]+$") and string.find(fields.height, "^[0-9]+$") then
  27. local side = tonumber(fields.side)
  28. local length = tonumber(fields.length)
  29. local height = tonumber(fields.height)
  30. if side < 100 and length < 100 and height < 100 then
  31. meta:set_int("farm_side", side)
  32. meta:set_int("farm_length", length)
  33. meta:set_int("farm_height", height)
  34. meta:set_string("formspec", get_harvester_formspec(side, length, height, get_label(meta)))
  35. end
  36. end
  37. end
  38. -- toggle on/off
  39. if fields.toggle then
  40. if meta:get_int("enabled") == 0 then
  41. meta:set_int("enabled", 1)
  42. else
  43. meta:set_int("enabled", 0)
  44. end
  45. end
  46. return true
  47. end
  48. local function find_next_digpos(data, area, minp, maxp)
  49. for y = minp.y, maxp.y do
  50. for z = minp.z, maxp.z do
  51. for x = minp.x, maxp.x do
  52. -- check if node on pos(x,y,z) is allowed for diggin e.a. in harvester_dig_node
  53. local nname = minetest.get_name_from_content_id(data[area:index(x, y, z)])
  54. if autofarmer.harvester_dig_nodes[nname] then
  55. -- harvest allowed
  56. return vector.new(x, y, z)
  57. end
  58. end
  59. end
  60. end
  61. end
  62. autofarmer.fastcross2 = {
  63. [1]={
  64. [0]={x=0,y=0,z=-1}},
  65. [-1]={
  66. [0]={x=0,y=0,z=1}},
  67. [0]={
  68. [1]={x=-1,y=0,z=0},
  69. [-1]={x=1,y=0,z=0}}
  70. }
  71. local function get_harvester_region(pos)
  72. local node = minetest.get_node(pos)
  73. local back_dir = minetest.facedir_to_dir(node.param2)
  74. -- determine current type and set size
  75. local meta = minetest.get_meta(pos)
  76. local flag = meta:get_string("power_flag")
  77. local farm_width_side = meta:get_int("farm_side")
  78. local farm_length = meta:get_int("farm_length")
  79. local farm_height = meta:get_int("farm_height")
  80. local sideways = autofarmer.fastcross[back_dir.x][back_dir.z]
  81. local left = vector.add(pos, vector.multiply(sideways, farm_width_side))
  82. left = vector.add(left, back_dir)
  83. left = vector.add(left, {x=0,y=-harvester_max_depth,z=0}) -- harvester depth down (one)
  84. local far = vector.add(pos, vector.multiply(sideways, -farm_width_side))
  85. far = vector.add(far, vector.multiply(back_dir, farm_length))
  86. far = vector.add(far, {x=0,y=-1,z=0})
  87. far = vector.add(far, {x=0,y=farm_height,z=0})
  88. local minx = math.min(far.x, left.x)
  89. local maxx = math.max(far.x, left.x)
  90. local minz = math.min(far.z, left.z)
  91. local maxz = math.max(far.z, left.z)
  92. local miny = math.min(far.y, left.y)
  93. local maxy = math.max(far.y, left.y)
  94. return
  95. {x=minx,y=miny,z=minz},
  96. {x=maxx,y=maxy,z=maxz}
  97. end
  98. local function harvester_dig(pos)
  99. local meta = minetest.get_meta(pos)
  100. local drops = {}
  101. local owner = meta:get_int("owner")
  102. local p1,p2 = get_harvester_region(pos)
  103. local vm = VoxelManip()
  104. local e1, e2 = vm:read_from_map(p1, p2)
  105. local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2})
  106. local data = vm:get_data()
  107. local digpos = find_next_digpos(data, area, p1, p2)
  108. if digpos then
  109. -- TODO probably check since it will be turned on again after power check / or do nothing?
  110. if minetest.is_protected and minetest.is_protected(digpos, owner) then
  111. meta:set_int("enabled", 0)
  112. return
  113. end
  114. local node = minetest.get_node(digpos)
  115. drops = minetest.get_node_drops(node.name) -- TODO get_node_drops(node, tool) optional tool...
  116. minetest.dig_node(digpos)
  117. if minetest.get_node(digpos).name == node.name then
  118. -- We tried to dig something undigable like a
  119. -- filled chest. Notice that we check for a node
  120. -- change, not for air. This is so that we get drops
  121. -- from things like concrete posts with platforms,
  122. -- which turn into regular concrete posts when dug.
  123. drops = {}
  124. end
  125. end
  126. return drops
  127. end
  128. local function send_items(items, pos, node)
  129. for _, item in pairs(items) do
  130. -- ejecting up seems the most obvious (and easy, since up is always up)
  131. technic.tube_inject_item(pos, pos, vector.new(0, 1, 0), item)
  132. end
  133. end
  134. local function calculate_demand(meta)
  135. local height = meta:get_int("farm_height")
  136. local length = meta:get_int("farm_length")
  137. local width = meta:get_int("farm_side")
  138. -- calculate proper width
  139. width = (width * 2) + 1
  140. -- adjust for exploiting multiplying by zero height
  141. if(height<=0) then height = 1 end
  142. if(width<=0) then width = 1 end
  143. if(length<=1) then length = 2 end
  144. local demand_per_node = autofarmer.harvester_demand_per_node
  145. -- require minimum power harvester_min_demand
  146. local demand = (height * length * width * demand_per_node)
  147. if(demand < autofarmer.harvester_min_demand) then
  148. demand = autofarmer.harvester_min_demand
  149. else
  150. demand = autofarmer.harvester_min_demand + demand
  151. end
  152. return demand
  153. end
  154. local function set_harvester_demand(meta)
  155. local prefix = meta:get_string("power_flag")
  156. local machine_name = S("%s Harvester"):format(prefix)
  157. local harvester_demand = calculate_demand(meta)
  158. -- get the right values for the right current TODO perhaps not, currently only enhanced MV implemented
  159. --if prefix == "LV" then harvester_demand = autofarmer.LV_harvester_demand end
  160. --if prefix == "MV" then harvester_demand = autofarmer.MV_harvester_demand end
  161. --if prefix == "HV" then harvester_demand = autofarmer.HV_harvester_demand end
  162. if meta:get_int("enabled") == 0 then
  163. meta:set_int(prefix.."_EU_demand", 0)
  164. meta:set_string("infotext", S("%s Disabled"):format(machine_name))
  165. else
  166. meta:set_int(prefix.."_EU_demand", harvester_demand)
  167. meta:set_string("infotext", S(meta:get_int(prefix.."_EU_input") >= harvester_demand and "%s Active" or "%s Unpowered"):format(machine_name))
  168. end
  169. meta:set_string("formspec", get_harvester_formspec(meta:get_int("farm_side"), meta:get_int("farm_length"), meta:get_int("farm_height"), get_label(meta)))
  170. end
  171. -- function called by technic mod
  172. local function harvester_run(pos, node)
  173. local meta = minetest.get_meta(pos)
  174. local prefix = meta:get_string("power_flag")
  175. -- create delay/chance so not every second something is harvested
  176. if math.random(autofarmer.MV_harvester_delay) == 1 then
  177. if meta:get_int("enabled") == 1 and meta:get_int(prefix.."_EU_input") >= meta:get_int(prefix.."_EU_demand") then
  178. -- do harvesting work
  179. local drops = harvester_dig(pos)
  180. send_items(drops, pos, node)
  181. end
  182. end
  183. set_harvester_demand(meta)
  184. end
  185. minetest.register_node("autofarmer:harvester", {
  186. description = "MV Harvester",
  187. tiles = {"moreores_tin_block.png", "moreores_tin_block.png",
  188. "moreores_tin_block.png", "moreores_tin_block.png",
  189. "moreores_tin_block.png^farming_tool_steelhoe.png", "moreores_tin_block.png"},
  190. paramtype2 = "facedir",
  191. groups = {cracky=2, tubedevice=1, technic_machine=1, technic_mv=1},
  192. connect_sides = {"bottom", "front", "left", "right"},
  193. tube = {
  194. connect_sides = {top = 1}, -- TODO front? (real world backside) but this was easiest since up (or down)
  195. -- is always the same regardless of orientation
  196. },
  197. mesecons = {effector = {
  198. action_on = function (pos, node)
  199. local meta = minetest.get_meta(pos)
  200. meta:set_int("enabled", 0)
  201. end,
  202. action_off = function (pos, node)
  203. local meta = minetest.get_meta(pos)
  204. meta:set_int("enabled", 1)
  205. end
  206. }},
  207. on_construct = function(pos)
  208. local side = 2
  209. local length = 5
  210. local meta = minetest.get_meta(pos)
  211. meta:set_string("infotext", "Harvester")
  212. meta:set_string("formspec", get_harvester_formspec(side, length, 1, get_label(meta)))
  213. meta:set_int("farm_side", side)
  214. meta:set_int("farm_length", length)
  215. meta:set_string("power_flag", "MV")
  216. local inv = meta:get_inventory()
  217. inv:set_size("main", 1)
  218. end,
  219. after_place_node = function(pos, placer, itemstack)
  220. local meta = minetest.get_meta(pos)
  221. meta:set_string("owner", placer:get_player_name())
  222. pipeworks.scan_for_tube_objects(pos)
  223. end,
  224. after_dig_node = pipeworks.scan_for_tube_objects,
  225. on_receive_fields = harvester_receive_fields,
  226. technic_run = harvester_run,
  227. -- old test function
  228. --on_punch = function(pos)
  229. -- toggle on/off
  230. -- local meta = minetest.get_meta(pos)
  231. -- if meta:get_int("enabled") == 1 then
  232. -- meta:set_int("enabled", 0)
  233. -- else
  234. -- meta:set_int("enabled", 1)
  235. -- end
  236. -- end,
  237. })
  238. technic.register_machine("MV", "autofarmer:harvester", technic.receiver)