actions_register.lua 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. -- infect a plant at pos and start timer
  2. farming.plant_infect = function(pos)
  3. local starttime=os.clock()
  4. local def = minetest.registered_nodes[minetest.get_node(pos).name]
  5. local infect_name=def.plant_name.."_infected"
  6. if not minetest.registered_nodes[infect_name] then
  7. return
  8. end
  9. if not def.groups.infectable then
  10. return
  11. end
  12. if not def.groups.step then
  13. return
  14. end
  15. local meta = minetest.get_meta(pos)
  16. local toremove=false
  17. if meta:get_int("farming:healthiness") then
  18. local healthiness=tonumber(meta:get_int("farming:healthiness"))
  19. if healthiness ~= nil then
  20. -- check for nearby plants which can protect against infections
  21. for i=1,3 do
  22. local protplant=minetest.find_node_near(pos,i,"group:infection_defense")
  23. if protplant ~= nil then
  24. ppdef=minetest.get_node(protplant)
  25. -- the protection plant has to be within their defined radius
  26. if ppdef.groups.infection_defense >= i then
  27. healthiness=healthiness+i*10
  28. end
  29. end
  30. end
  31. end
  32. if healthiness>farming.health_threshold then
  33. meta:set_int("farming:healthiness",healthiness-meta:get_int("farming:weakness"))
  34. else
  35. meta:set_int("farming:healthiness",farming.health_threshold)
  36. meta:set_int("farming:weakness",5)
  37. toremove=true
  38. end
  39. else
  40. toremove=true
  41. end
  42. if toremove then
  43. local placenode = {name = infect_name}
  44. if def.place_param2 then
  45. placenode.param2 = def.place_param2
  46. end
  47. minetest.swap_node(pos, placenode)
  48. local meta = minetest.get_meta(pos)
  49. meta:set_int("farming:step",def.groups["step"])
  50. minetest.get_node_timer(pos):start(math.random(farming.wait_min,farming.wait_max))
  51. end
  52. --table.insert(farming.time_plantinfect,1000*(os.clock()-starttime))
  53. end
  54. -- cures a plant at pos, restoring at last saved step
  55. farming.plant_cured = function(pos)
  56. local starttime=os.clock()
  57. local node = minetest.get_node(pos)
  58. local name = node.name
  59. local def = minetest.registered_nodes[name]
  60. local meta = minetest.get_meta(pos)
  61. local cured_step=meta:get_int("farming:step")
  62. if cured_step == nil then cured_stel = 1 end
  63. local cured_name=def.step_name.."_"..cured_step
  64. if not minetest.registered_nodes[cured_name] then
  65. return
  66. end
  67. local placenode = {name = cured_name}
  68. if def.place_param2 then
  69. placenode.param2 = def.place_param2
  70. end
  71. minetest.swap_node(pos, placenode)
  72. --table.insert(farming.time_plantcured,1000*(os.clock()-starttime))
  73. end
  74. -- function for handle punching of a crop
  75. -- if at last step than go back one step and give puncher one fruit
  76. -- then start timer again
  77. farming.punch_step = function(pos, node, puncher, pointed_thing)
  78. local starttime=os.clock()
  79. local def = minetest.registered_nodes[node.name]
  80. if def.groups.punchable == nil then
  81. return
  82. end
  83. -- only give fruit and go back if pre step is defined
  84. if def.pre_step == nil then
  85. return
  86. end
  87. if puncher ~= nil and puncher:get_player_name() ~= "" then
  88. -- give one item only if no billhook is used
  89. puncher:get_inventory():add_item('main',def.drop_item)
  90. end
  91. minetest.swap_node(pos, {name=def.pre_step,
  92. param2=def.place_param2 or 3})
  93. -- new timer needed?
  94. local pre_def=minetest.registered_nodes[def.pre_step]
  95. local meta = minetest.get_meta(pos)
  96. meta:set_int("farming:step",pre_def.groups.step)
  97. if pre_def.next_step then
  98. local waittime=math.random(pre_def.grow_time_min or 100, pre_def.grow_time_max or 200) * farming.factor_regrow
  99. minetest.get_node_timer(pos):start(math.random(pre_def.grow_time_min or 100, pre_def.grow_time_max or 200))
  100. end
  101. --table.insert(farming.time_plantpunch,1000*(os.clock()-starttime))
  102. return
  103. end
  104. -- function for digging crops
  105. -- if dug with scythe by change you harvest more
  106. --farming.dig_harvest = function(pos, node, digger)
  107. farming.register_on_harvest(function(pos, node, digger)
  108. local starttime=os.clock()
  109. local def = minetest.registered_nodes[node.name]
  110. local tool_def = digger:get_wielded_item():get_definition()
  111. if tool_def.groups.scythe and def.drop_item then
  112. if tool_def.farming_change ~= nil then
  113. if math.random(1,tool_def.farming_change)==1 then
  114. digger:get_inventory():add_item('main',def.drop_item)
  115. end
  116. end
  117. end
  118. -- print(dump(def.drop))
  119. minetest.node_dig(pos,node,digger)
  120. --table.insert(farming.time_digharvest,1000*(os.clock()-starttime))
  121. end)
  122. -- timer function for infected plants
  123. -- the step of plant is reduced till zero then the plant dies
  124. -- nearby crops are infected by change given in configuration
  125. -- normally in monoculture the infection rate is higher
  126. farming.timer_infect = function(pos,elapsed)
  127. -- local starttime=os.clock()
  128. local node = minetest.get_node(pos)
  129. local def = minetest.registered_nodes[node.name]
  130. local meta = minetest.get_meta(pos)
  131. -- if no step is saved in metadata (should not be, but...) , removing plant
  132. if meta:get_int("farming:step") == nil then
  133. minetest.swap_node(pos, {name="air"})
  134. return
  135. end
  136. -- if zero step is reached, plant dies
  137. if meta:get_int("farming:step") == 0 then
  138. minetest.swap_node(pos, {name="default:grass_"..math.random(1,4)})
  139. return
  140. end
  141. local infected = 0
  142. -- check for monoculture and infect nearby plants
  143. if def.infect_rate_monoculture ~= nil then
  144. local monoculture=minetest.find_nodes_in_area(vector.subtract(pos,2),vector.add(pos,2),"group:"..def.plant_name)
  145. if monoculture ~= nil then
  146. for i = 1,#monoculture do
  147. if math.random(1,math.max(2,def.infect_rate_monoculture))==1 then
  148. farming.plant_infect(monoculture[i])
  149. infected=infected+1
  150. end
  151. end
  152. end
  153. end
  154. -- if no monoculture plant was infected try other crops
  155. -- check for nearby other plants and infect them
  156. if infected == 0 then
  157. if def.infect_rate_base ~= nil then
  158. local culture=minetest.find_nodes_in_area(vector.subtract(pos,3),vector.add(pos,3),"group:infectable")
  159. if culture ~= nil then
  160. for i = 1,#culture do
  161. if math.random(1,math.max(2,def.infect_rate_base))==1 then
  162. farming.plant_infect(culture[i])
  163. infected=infected+1
  164. end
  165. end
  166. end
  167. end
  168. end
  169. meta:set_int("farming:step",meta:get_int("farming:step")-1)
  170. minetest.get_node_timer(pos):start(math.random(farming.wait_min,farming.wait_max))
  171. --table.insert(farming.time_infect,1000*(os.clock()-starttime))
  172. end
  173. -- timer function called for a step to grow
  174. -- if enough light then grow to next step
  175. -- if a following step or wilt is defined then calculate new time and set timer
  176. farming.timer_step = function(pos, elapsed)
  177. local starttime=os.clock()
  178. local def = minetest.registered_nodes[minetest.get_node(pos).name]
  179. -- check for enough light
  180. if not def.next_step then
  181. return
  182. end
  183. local light = minetest.get_node_light(pos)
  184. local pdef=farming.registered_plants[def.plant_name]
  185. if not light or light < pdef.light_min or light > pdef.light_max then
  186. minetest.get_node_timer(pos):start(math.random(farming.wait_min, farming.wait_max))
  187. return
  188. end
  189. local next_def=minetest.registered_nodes[def.next_step]
  190. minetest.swap_node(pos, {name=def.next_step,
  191. param2=def.place_param2 or 3})
  192. local meta = minetest.get_meta(pos)
  193. if next_def.groups.farming_wilt ~= nil then
  194. if meta:get_int("farming:weakness") == nil then
  195. farming.set_node_metadata(pos)
  196. end
  197. meta:set_int("farming:weakness",math.ceil(meta:get_int("farming:weakness")/2))
  198. else
  199. meta:set_int("farming:step",next_def.groups.step)
  200. end
  201. if next_def.groups.farming_fullgrown ~= nil then
  202. meta:set_int("farming:seeds",1)
  203. else
  204. meta:set_int("farming:seeds",0)
  205. end
  206. -- new timer needed?
  207. local wait_factor = 1
  208. -- check for config values
  209. local lightamount=meta:get_int("farming:lightamount")
  210. if lightamount ~= nil then
  211. local ls = farming.light_stat[tostring(def.light_min)]
  212. if ls.amount ~= nil and lightamount > 0 then
  213. -- time till next step is stretched. Less light means longer growing time
  214. wait_factor = ls.amount / lightamount
  215. end
  216. else
  217. wait_factor = math.max(0.75,def.light_min/minetest.get_node_light(pos,0.5))
  218. end
  219. -- using light at midday to increase or decrease growing time
  220. local wait_min = math.ceil(def.grow_time_min * wait_factor)
  221. local wait_max = math.ceil(def.grow_time_max * wait_factor)
  222. if wait_max <= wait_min then wait_max = 2*wait_min end
  223. local timespeed=minetest.settings:get("time_speed")
  224. local time_wait=math.random(wait_min,wait_max)
  225. local local_rwt=time_wait*timespeed/(86400)
  226. local daystart=meta:get_float("farming:daystart")
  227. local acttime=minetest.get_timeofday()
  228. if math.abs(acttime+local_rwt-0.5)>(0.5-daystart) then
  229. time_wait=86400*(1+daystart-acttime)/timespeed
  230. end
  231. minetest.get_node_timer(pos):start(time_wait)
  232. --table.insert(farming.time_steptimer,1000*(os.clock()-starttime))
  233. return
  234. end
  235. -- Seed placement
  236. -- adopted from minetest-game
  237. farming.place_seed = function(itemstack, placer, pointed_thing, plantname)
  238. local starttime=os.clock()
  239. -- check if pointing at a node
  240. if not pointed_thing then
  241. return itemstack
  242. end
  243. if pointed_thing.type ~= "node" then
  244. return itemstack
  245. end
  246. -- check if pointing at the top of the node
  247. if pointed_thing.above.y ~= pointed_thing.under.y+1 then
  248. return itemstack
  249. end
  250. local player_name = placer and placer:get_player_name() or ""
  251. if minetest.is_protected(pointed_thing.under, player_name) then
  252. minetest.record_protection_violation(pointed_thing.under, player_name)
  253. return
  254. end
  255. if minetest.is_protected(pointed_thing.above, player_name) then
  256. minetest.record_protection_violation(pointed_thing.above, player_name)
  257. return
  258. end
  259. local under = minetest.get_node(pointed_thing.under)
  260. -- return if any of the nodes is not registered
  261. if not minetest.registered_nodes[under.name] then
  262. return itemstack
  263. end
  264. local above = minetest.get_node(pointed_thing.above)
  265. if not minetest.registered_nodes[above.name] then
  266. return itemstack
  267. end
  268. -- check if you can replace the node above the pointed node
  269. if not minetest.registered_nodes[above.name].buildable_to then
  270. return itemstack
  271. end
  272. local udef = minetest.registered_nodes[under.name]
  273. local pdef = minetest.registered_nodes[plantname]
  274. -- check if pointing at soil and seed needs soil
  275. if minetest.get_item_group(under.name,"soil") < 2 then
  276. if minetest.get_item_group(plantname,"on_soil") >= 1 then
  277. return
  278. else
  279. -- check if node is correct one
  280. local plant_def=farming.registered_plants[pdef.plant_name]
  281. -- check for correct temperature
  282. if pointed_thing.under.y < plant_def.elevation_min or pointed_thing.under.y > plant_def.elevation_max then
  283. minetest.chat_send_player(player_name,"Elevation must be between "..plant_def.elevation_min.." and "..plant_def.elevation_max)
  284. return
  285. end
  286. if minetest.get_heat(pointed_thing.under) < plant_def.temperature_min or minetest.get_heat(pointed_thing.under) > plant_def.temperature_max then
  287. minetest.chat_send_player(player_name,"Temperature "..minetest.get_heat(pt.under).." is out of range for planting.")
  288. return
  289. end
  290. if minetest.get_humidity(pointed_thing.under) < plant_def.humidity_min or minetest.get_humidity(pointed_thing.under) > plant_def.humidity_max then
  291. minetest.chat_send_player(player_name,"Humidity "..minetest.get_humidity(pt.under).." is out of range for planting.")
  292. return
  293. end
  294. end
  295. end
  296. -- add the node and remove 1 item from the itemstack
  297. minetest.add_node(pointed_thing.above, {name = plantname, param2 = 1})
  298. local wait_min=farming.wait_min or 120
  299. local wait_max=farming.wait_max or 240
  300. if pdef.grow_time_min then
  301. wait_min=pdef.grow_time_min
  302. end
  303. if pdef.grow_time_max then
  304. wait_max=pdef.grow_time_max
  305. end
  306. minetest.get_node_timer(pointed_thing.above):start(math.random(wait_min, wait_max))
  307. local meta = minetest.get_meta(pointed_thing.above)
  308. meta:set_int("farming:step",0)
  309. farming.set_node_metadata(pointed_thing.above,placer)
  310. if not (creative and creative.is_enabled_for
  311. and creative.is_enabled_for(player_name)) then
  312. itemstack:take_item()
  313. end
  314. --table.insert(farming.time_placeseed,1000*(os.clock()-starttime))
  315. return itemstack
  316. end
  317. -- timer function for growing seed
  318. -- after the time out the first step of plant in placed
  319. farming.timer_seed = function(pos, elapsed)
  320. local starttime=os.clock()
  321. local node = minetest.get_node(pos)
  322. local def = minetest.registered_nodes[node.name]
  323. local soil_node = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z})
  324. if not soil_node then
  325. minetest.get_node_timer(pos):start(math.random(farming.wait_min, farming.wait_max))
  326. return
  327. end
  328. -- omitted is a check for light, we assume seeds can germinate in the dark.
  329. local placenode = {name = def.next_step}
  330. if def.place_param2 then
  331. placenode.param2 = def.place_param2 or 3
  332. end
  333. minetest.swap_node(pos, placenode)
  334. local meta = minetest.get_meta(pos)
  335. if def.next_step then
  336. meta:set_int("farming:step",minetest.registered_nodes[def.next_step].groups.step)
  337. -- using light at midday to increase or decrease growing time
  338. local local_light_max = minetest.get_node_light(pos,0.5)
  339. local wait_factor = math.max(0.75,def.light_min/local_light_max)
  340. local wait_min = math.ceil(def.grow_time_min * wait_factor)
  341. local wait_max = math.ceil(def.grow_time_max * wait_factor)
  342. if wait_max <= wait_min then wait_max = 2*wait_min end
  343. local node_timer=math.random(wait_min, wait_max)
  344. minetest.get_node_timer(pos):start(node_timer)
  345. return
  346. end
  347. --table.insert(farming.time_seedtimer,1000*(os.clock()-starttime))
  348. end
  349. -- timer function for wilt plants
  350. -- normal plants will die after the time
  351. -- weed like nettles can spread to neighbour places
  352. farming.timer_wilt = function(pos, elapsed)
  353. local starttime=os.clock()
  354. local node = minetest.get_node(pos)
  355. local def = minetest.registered_nodes[node.name]
  356. if def.groups.wiltable == 3 then -- nettle or weed
  357. -- determine all nearby nodes with soil
  358. local farming_nearby=minetest.find_nodes_in_area(vector.subtract(pos,2),vector.add(pos,2),"group:farming")
  359. -- within radius 2 not more than 4 nettles should be for further spreading
  360. if #farming_nearby <= 4 then
  361. local neighb=minetest.find_nodes_in_area(vector.subtract(pos,2),vector.add(pos,2),"group:soil")
  362. if neighb ~= nil then
  363. local freen={}
  364. -- get soil nodes with air above
  365. for j=1,#neighb do
  366. local jpos=neighb[j]
  367. if basic_functions.has_value({"air","default:grass_1","default:grass_2","default:grass_3","default:grass_4","default:grass_5"},minetest.get_node({x=jpos.x,y=jpos.y+1,z=jpos.z}).name) then
  368. table.insert(freen,1,jpos)
  369. end
  370. end
  371. -- randomly pick one and spread
  372. if #freen >= 1 then
  373. local npos={x=jpos.x,y=jpos.y+1,z=jpos.z}
  374. local jpos=freen[math.random(1,#freen)]
  375. minetest.add_node(npos, {name = def.seed_name, param2 = 1})
  376. farming.set_node_metadata(npos)
  377. minetest.get_node_timer(npos):start(def.grow_time_min or 10)
  378. end
  379. end
  380. end
  381. -- after spreading the source can be removed, go back one step or stay
  382. -- with higher change to be removed if already several similar plants are nearby
  383. local wran=math.random(1,math.max(3,#farming_nearby))
  384. if wran >= 3 then
  385. minetest.swap_node(pos, {name="air"})
  386. end
  387. if wran == 2 then
  388. if def.pre_step ~= nil then
  389. minetest.swap_node(pos, {name=def.pre_step, param2=1})
  390. minetest.get_node_timer(pos):start(math.random(def.grow_time_min or 10,def.grow_time_max or 20))
  391. end
  392. end
  393. if wran == 1 then
  394. minetest.get_node_timer(pos):start(math.random(def.grow_time_min or 10,def.grow_time_max or 20))
  395. end
  396. else --normal crop
  397. minetest.set_node(pos, {name="air"})
  398. minetest.add_node(pos, {name="default:grass_"..math.random(1,5),param2=1})
  399. end
  400. --table.insert(farming.time_wilttimer,1000*(os.clock()-starttime))
  401. end
  402. farming.seed_on_place = function(itemstack, placer, pointed_thing)
  403. local node = minetest.get_node(pointed_thing.under)
  404. local udef = minetest.registered_nodes[node.name]
  405. local plantname = itemstack:get_name()
  406. if udef and udef.on_rightclick and
  407. not (placer and placer:is_player() and
  408. placer:get_player_control().sneak) then
  409. return udef.on_rightclick(pointed_thing.under, node, placer, itemstack,
  410. pointed_thing) or itemstack
  411. end
  412. return farming.place_seed(itemstack, placer, pointed_thing, plantname)
  413. end
  414. -- using tools
  415. -- adopted from minetest-games
  416. farming.dig_by_tool = function(itemstack, user, pointed_thing, uses)
  417. local starttime=os.clock()
  418. -- check if pointing at a node
  419. if not pointed_thing then
  420. return
  421. end
  422. local under = minetest.get_node(pointed_thing.under)
  423. local p = {x=pointed_thing.under.x, y=pointed_thing.under.y+1, z=pointed_thing.under.z}
  424. local above = minetest.get_node(p)
  425. -- return if any of the nodes is not registered
  426. if not minetest.registered_nodes[under.name] then
  427. return
  428. end
  429. if not minetest.registered_nodes[above.name] then
  430. return
  431. end
  432. -- check if the node above the pointed thing is air
  433. if above.name ~= "air" then
  434. return
  435. end
  436. if minetest.is_protected(pointed_thing.under, user:get_player_name()) then
  437. minetest.record_protection_violation(pointed_thing.under, user:get_player_name())
  438. return
  439. end
  440. if minetest.is_protected(pointed_thing.above, user:get_player_name()) then
  441. minetest.record_protection_violation(pointed_thing.above, user:get_player_name())
  442. return
  443. end
  444. if not (creative and creative.is_enabled_for
  445. and creative.is_enabled_for(user:get_player_name())) then
  446. -- wear tool
  447. local wdef = itemstack:get_definition()
  448. itemstack:add_wear(65535/(wdef.max_uses-1))
  449. minetest.node_dig(pt.under,under,user)
  450. -- tool break sound
  451. if itemstack:get_count() == 0 and wdef.sound and wdef.sound.breaks then
  452. minetest.sound_play(wdef.sound.breaks, {pos = pointed_thing.above, gain = 0.5})
  453. end
  454. end
  455. --table.insert(farming.time_tooldig,1000*(os.clock()-starttime))
  456. return itemstack
  457. end
  458. farming.use_picker = function(itemstack, user, pointed_thing,uses)
  459. local starttime=os.clock()
  460. -- check if pointing at a node
  461. if not pointed_thing then
  462. return
  463. end
  464. if pointed_thing.type ~= "node" then
  465. return
  466. end
  467. local pos = pointed_thing.under
  468. local under = minetest.get_node(pos)
  469. -- return if any of the nodes is not registered
  470. if not minetest.registered_nodes[under.name] then
  471. return
  472. end
  473. if minetest.is_protected(pos, user:get_player_name()) then
  474. minetest.record_protection_violation(pos, user:get_player_name())
  475. return
  476. end
  477. local pdef=minetest.registered_nodes[under.name]
  478. -- check if pointing at punchable crop
  479. if pdef.groups.punchable == nil then
  480. return
  481. end
  482. -- check if plant is full grown
  483. if pdef.groups.farming_fullgrown == nil then
  484. return
  485. end
  486. -- check if seeds can be extracted
  487. if pdef.groups.seed_extractable == nil then
  488. return
  489. end
  490. -- check if seeds are available
  491. local meta = minetest.get_meta(pos)
  492. if meta:get_int("farming:seeds") == nil then
  493. meta:set_int("farming:seeds",0)
  494. return
  495. else
  496. if meta:get_int("farming:seeds")==0 then
  497. return
  498. end
  499. end
  500. local tdef=itemstack:get_definition()
  501. if not (creative and creative.is_enabled_for
  502. and creative.is_enabled_for(user:get_player_name())) then
  503. -- wear tool
  504. itemstack:add_wear(65535/(uses-1))
  505. -- tool break sound
  506. if itemstack:get_count() == 0 and tdef.sound and tdef.sound.breaks then
  507. minetest.sound_play(tdef.sound.breaks, {pos = pointed_thing.above, gain = 0.5})
  508. end
  509. end
  510. user:get_inventory():add_item('main',pdef.seed_name)
  511. if math.random(1,3)==1 then
  512. user:get_inventory():add_item('main',pdef.seed_name)
  513. end
  514. -- call punching function of crop: normally go back one step and start timer
  515. minetest.punch_node(pointed_thing.under)
  516. local meta = minetest.get_meta(pos)
  517. meta:set_int("farming:seeds",0)
  518. --table.insert(farming.time_usehook,1000*(os.clock()-starttime))
  519. return itemstack
  520. end
  521. -- function for using billhook on punchable fruits
  522. -- add wear to billhook and give player by change one more fruit
  523. farming.use_billhook = function(itemstack, user, pointed_thing, uses)
  524. local starttime=os.clock()
  525. -- check if pointing at a node
  526. if not pointed_thing then
  527. return
  528. end
  529. if pointed_thing.type ~= "node" then
  530. return
  531. end
  532. local under = minetest.get_node(pointed_thing.under)
  533. -- return if any of the nodes is not registered
  534. if not minetest.registered_nodes[under.name] then
  535. return
  536. end
  537. local pdef=minetest.registered_nodes[under.name]
  538. -- check if pointing at punchable crop
  539. if pdef.groups.punchable == nil then
  540. return
  541. end
  542. -- check if plant is full grown
  543. if pdef.groups.farming_fullgrown == nil then
  544. return
  545. end
  546. if minetest.is_protected(pointed_thing.under, user:get_player_name()) then
  547. minetest.record_protection_violation(pointed_thing.under, user:get_player_name())
  548. return
  549. end
  550. local tdef=itemstack:get_definition()
  551. if not (creative and creative.is_enabled_for
  552. and creative.is_enabled_for(user:get_player_name())) then
  553. -- wear tool
  554. itemstack:add_wear(65535/(uses-1))
  555. -- tool break sound
  556. if itemstack:get_count() == 0 and tdef.sound and tdef.sound.breaks then
  557. minetest.sound_play(tdef.sound.breaks, {pos = pointed_thing.above, gain = 0.5})
  558. end
  559. end
  560. user:get_inventory():add_item('main',pdef.drop_item)
  561. if tdef.farming_change ~= nil then
  562. if math.random(1,tdef.farming_change)==1 then
  563. user:get_inventory():add_item('main',pdef.drop_item)
  564. end
  565. end
  566. -- call punching function of crop: normally go back one step and start timer
  567. minetest.punch_node(pointed_thing.under)
  568. --table.insert(farming.time_usehook,1000*(os.clock()-starttime))
  569. return itemstack
  570. end
  571. -- calculate light amount on a position for a given light_min
  572. farming.calc_light=function(pos,pdef)
  573. local starttime=os.clock()
  574. -- calculating
  575. local day_start=99999
  576. local light_amount=0
  577. local light_min=pdef.light_min
  578. -- run from 5:00 till 12:00 in 6min steps
  579. for i=50,120 do
  580. local reli=i/240
  581. local nl=minetest.get_node_light(pos,reli)
  582. if nl>light_min then
  583. light_amount=light_amount+nl
  584. if day_start > 1000 then day_start = i end
  585. end
  586. end
  587. if day_start > 240 then
  588. day_start=120
  589. end
  590. --table.insert(farming.time_calclight,1000*(os.clock()-starttime))
  591. local outdata={day_start=day_start,
  592. light_amount=light_amount,
  593. }
  594. return outdata
  595. end
  596. -- calculate several meta data for a node and save in node storage
  597. farming.set_node_metadata=function(pos,player)
  598. local starttime=os.clock()
  599. local base_rate = 5
  600. local node = minetest.get_node(pos)
  601. local def = minetest.registered_nodes[node.name]
  602. local pdef = farming.registered_plants[def.plant_name]
  603. local ill_rate=base_rate * (pdef.light_max-minetest.get_node_light(pos,0.5))/(pdef.light_max-pdef.light_min)
  604. local player_meta=99
  605. if player ~= nil then
  606. player_meta=player:get_meta()
  607. end
  608. -- calc coeff for temperature
  609. local ill_temp=(base_rate * math.sqrt(math.min(minetest.get_heat(pos)-pdef.temperature_min,pdef.temperature_max-minetest.get_heat(pos))/(pdef.temperature_max-pdef.temperature_min)))
  610. -- negative coeff means, it is out of range
  611. if ill_temp < 0 then
  612. ill_temp = (ill_temp * (-0.75))
  613. end
  614. -- calc coeff for humidity
  615. local ill_hum=(base_rate * math.sqrt(math.min(minetest.get_humidity(pos)-pdef.humidity_min,pdef.humidity_max-minetest.get_humidity(pos))/(pdef.humidity_max-pdef.humidity_min)))
  616. -- negative coeff means, it is out of range
  617. if ill_hum < 0 then
  618. ill_hum = (ill_hum * (-0.75))
  619. end
  620. local infect_rate = 1
  621. if pdef.groups.infectable then
  622. infect_rate = pdef.groups.infectable
  623. end
  624. ill_rate = math.ceil((ill_rate + ill_temp + ill_hum)/infect_rate)
  625. if player_meta ~= 99 then
  626. if player_meta:get_int("xp:farming") ~= nil then
  627. ill_rate = math.ceil(ill_rate * player_meta:get_int("xp:farming"))
  628. end
  629. end
  630. local meta = minetest.get_meta(pos)
  631. -- weakness as rate, how easily a crop can be infected
  632. meta:set_int("farming:weakness",ill_rate)
  633. -- healthiness as mechanism to controll if a crop will be infected
  634. meta:set_int("farming:healthiness",50+ill_rate)
  635. local lightcalc=farming.calc_light(pos,pdef)
  636. -- daytime, when light reach light_min
  637. meta:set_float("farming:daystart",lightcalc.day_start/240)
  638. -- amount of light the crop gets till midday
  639. meta:set_int("farming:lightamount",lightcalc.light_amount)
  640. -- init the amount of seed available at the crop
  641. meta:set_int("farming:seeds",0)
  642. --table.insert(farming.time_setmeta,1000*(os.clock()-starttime))
  643. end