init.lua 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. -- EDITED BY FREEGAMERS, Fall, 2019
  2. -- CHANGES:
  3. -- INCLUDED NICER TEXTURES FROM CHURCH_CANDLES MOD
  4. -- USED TEXTURES FROM DEFAULT TO REDUCE REDUNDANCY,
  5. -- REMOVED AUTOMATION VIA INDUSTRIAL HIVE & PIPEWORKS SUPPORT TO RETAIN PLAYER ENGAGEMENT.
  6. -- CLEANED UP DESCRIPTION FIELDS' CASING
  7. -- REMOVE BACKWARDS COMPATIBLITY
  8. -- ADDED LOCATIONAL SOUND EFFECTS.
  9. -- TODO: ADD HONEY LIQUID / BUCKET, maybe a honey/bee biomes.
  10. -- TODO: Giant Bee Mob for mobs_Creatures.
  11. --Bees by Bas080
  12. --Note: This branch was modified by clockgen in summer, 2019.
  13. --Version 2.2
  14. --License WTFPL
  15. --VARIABLES
  16. local bees = {}
  17. local formspecs = {}
  18. --FUNCTIONS
  19. function formspecs.hive_wild(pos, grafting)
  20. local spos = pos.x .. ',' .. pos.y .. ',' ..pos.z
  21. local formspec =
  22. 'size[8,9]'..
  23. 'list[nodemeta:'.. spos .. ';combs;1.5,3;5,1;]'..
  24. 'list[current_player;main;0,5;8,4;]'
  25. if grafting then
  26. formspec = formspec..'list[nodemeta:'.. spos .. ';queen;3.5,1;1,1;]'
  27. end
  28. return formspec
  29. end
  30. function formspecs.hive_artificial(pos)
  31. local spos = pos.x..','..pos.y..','..pos.z
  32. local formspec =
  33. 'size[8,9]'..
  34. 'list[nodemeta:'..spos..';queen;3.5,1;1,1;]'..
  35. 'list[nodemeta:'..spos..';frames;0,3;8,1;]'..
  36. 'list[current_player;main;0,5;8,4;]'
  37. return formspec
  38. end
  39. function bees.polinate_flower(pos, flower)
  40. local spawn_pos = { x=pos.x+math.random(-3,3) , y=pos.y+math.random(-3,3) , z=pos.z+math.random(-3,3) }
  41. local floor_pos = { x=spawn_pos.x , y=spawn_pos.y-1 , z=spawn_pos.z }
  42. local spawn = minetest.get_node(spawn_pos).name
  43. local floor = minetest.get_node(floor_pos).name
  44. if floor == 'default:dirt_with_grass' and spawn == 'air' then
  45. minetest.set_node(spawn_pos, {name=flower})
  46. end
  47. end
  48. minetest.register_node('bees:extractor', {
  49. description = 'Honey Extractor Machine',
  50. tiles = {"bees_extractor_top.png", "bees_extractor_bottom.png", "bees_extractor_side.png", "bees_extractor_side.png", "bees_extractor_side.png", "bees_extractor_front.png"},
  51. paramtype = "light",
  52. paramtype2 = "facedir",
  53. drawtype = "nodebox",
  54. place_param2 = 0,
  55. groups = {choppy=2,oddly_breakable_by_hand=2},
  56. sounds = default.node_sound_wood_defaults(),
  57. node_box = {
  58. type = "fixed",
  59. fixed = {
  60. {-0.4375, -0.5, -0.4375, 0.4375, 0, 0.4375},
  61. {-0.375, -0.0625, -0.375, 0.375, 0.5, 0.375},
  62. {-0.4375, 0.375, -0.4375, 0.4375, 0.4375, 0.4375},
  63. {0.375, 0, -0.4375, 0.4375, 0.4375, -0.375},
  64. {-0.4375, 0, -0.4375, -0.375, 0.4375, -0.375},
  65. {-0.4375, 0, 0.375, -0.375, 0.4375, 0.4375},
  66. {0.375, 0, 0.375, 0.4375, 0.4375, 0.4375},
  67. },
  68. },
  69. selection_box = {
  70. type = "fixed",
  71. fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
  72. },
  73. on_construct = function(pos, node)
  74. local meta = minetest.get_meta(pos)
  75. local inv = meta:get_inventory()
  76. local pos = pos.x..','..pos.y..','..pos.z
  77. inv:set_size('frames_filled' ,1)
  78. inv:set_size('frames_emptied' ,1)
  79. inv:set_size('bottles_empty' ,1)
  80. inv:set_size('bottles_full' ,1)
  81. inv:set_size('wax',1)
  82. meta:set_string('formspec',
  83. 'size[8,9]'..
  84. --input
  85. 'list[nodemeta:'..pos..';frames_filled;2,1;1,1;]'..
  86. 'list[nodemeta:'..pos..';bottles_empty;2,3;1,1;]'..
  87. --output
  88. 'list[nodemeta:'..pos..';frames_emptied;5,0.5;1,1;]'..
  89. 'list[nodemeta:'..pos..';wax;5,2;1,1;]'..
  90. 'list[nodemeta:'..pos..';bottles_full;5,3.5;1,1;]'..
  91. --player inventory
  92. 'list[current_player;main;0,5;8,4;]'
  93. )
  94. end,
  95. on_timer = function(pos, node)
  96. local meta = minetest.get_meta(pos)
  97. local inv = meta:get_inventory()
  98. if not inv:contains_item('frames_filled','bees:frame_full') or not inv:contains_item('bottles_empty','vessels:glass_bottle') then
  99. return
  100. end
  101. if inv:room_for_item('frames_emptied', 'bees:frame_empty')
  102. and inv:room_for_item('wax','bees:wax')
  103. and inv:room_for_item('bottles_full', 'bees:bottle_honey') then
  104. --add to output
  105. inv:add_item('frames_emptied', 'bees:frame_empty')
  106. inv:add_item('wax', 'bees:wax')
  107. inv:add_item('bottles_full', 'bees:bottle_honey')
  108. --remove from input
  109. inv:remove_item('bottles_empty','vessels:glass_bottle')
  110. inv:remove_item('frames_filled','bees:frame_full')
  111. local p = {x=pos.x+math.random()-0.5, y=pos.y+math.random()-0.5, z=pos.z+math.random()-0.5}
  112. --wax flying all over the place
  113. minetest.add_particle({
  114. pos = {x=pos.x, y=pos.y, z=pos.z},
  115. vel = {x=math.random(-4,4),y=math.random(8),z=math.random(-4,4)},
  116. acc = {x=0,y=-6,z=0},
  117. expirationtime = 2,
  118. size = math.random(1,3),
  119. collisiondetection = false,
  120. texture = 'bees_wax_particle.png',
  121. })
  122. local timer = minetest.get_node_timer(pos)
  123. timer:start(5)
  124. else
  125. local timer = minetest.get_node_timer(pos)
  126. timer:start(1) -- Try again in 1 second
  127. end
  128. end,
  129. tube = {
  130. insert_object = function(pos, node, stack, direction)
  131. local meta = minetest.get_meta(pos)
  132. local inv = meta:get_inventory()
  133. local timer = minetest.get_node_timer(pos)
  134. if stack:get_name() == "bees:frame_full" then
  135. if inv:is_empty("frames_filled") then
  136. timer:start(5)
  137. end
  138. return inv:add_item("frames_filled",stack)
  139. elseif stack:get_name() == "vessels:glass_bottle" then
  140. if inv:is_empty("bottles_empty") then
  141. timer:start(5)
  142. end
  143. return inv:add_item("bottles_empty",stack)
  144. end
  145. return stack
  146. end,
  147. can_insert = function(pos,node,stack,direction)
  148. local meta = minetest.get_meta(pos)
  149. local inv = meta:get_inventory()
  150. if stack:get_name() == "bees:frame_full" then
  151. return inv:room_for_item("frames_filled",stack)
  152. elseif stack:get_name() == "vessels:glass_bottle" then
  153. return inv:room_for_item("bottles_empty",stack)
  154. end
  155. return false
  156. end,
  157. input_inventory = {"frames_emptied", "bottles_full", "wax"},
  158. connect_sides = {left=1, right=1, back=1, front=1, bottom=1, top=1}
  159. },
  160. on_metadata_inventory_put = function(pos, listname, index, stack, player)
  161. local timer = minetest.get_node_timer(pos)
  162. local meta = minetest.get_meta(pos)
  163. local inv = meta:get_inventory()
  164. if inv:get_stack(listname, 1):get_count() == stack:get_count() then -- inv was empty -> start the timer
  165. timer:start(5) --create a honey bottle and empty frame and wax every 5 seconds
  166. end
  167. end,
  168. allow_metadata_inventory_put = function(pos, listname, index, stack, player)
  169. if minetest.is_protected(pos, player:get_player_name()) then
  170. return 0
  171. end
  172. if (listname == 'bottles_empty' and stack:get_name() == 'vessels:glass_bottle') or (listname == 'frames_filled' and stack:get_name() == 'bees:frame_full') then
  173. return stack:get_count()
  174. else
  175. return 0
  176. end
  177. end,
  178. allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
  179. return 0
  180. end,
  181. allow_metadata_inventory_take = function(pos, listname, index, stack, player)
  182. if minetest.is_protected(pos,player:get_player_name()) then
  183. return 0
  184. end
  185. return stack:get_count()
  186. end,
  187. })
  188. minetest.register_node('bees:bees', {
  189. description = 'Flying Bees',
  190. drawtype = 'plantlike',
  191. paramtype = 'light',
  192. groups = { not_in_creative_inventory=1 },
  193. tiles = {
  194. {
  195. name='bees_strip.png',
  196. animation={type='vertical_frames', aspect_w=16,aspect_h=16, length=2.0}
  197. }
  198. },
  199. damage_per_second = 1,
  200. walkable = false,
  201. buildable_to = true,
  202. pointable = false,
  203. on_punch = function(pos, node, puncher)
  204. local health = puncher:get_hp()
  205. puncher:set_hp(health-2)
  206. end,
  207. })
  208. minetest.register_node('bees:hive_wild', {
  209. description = 'Wild Bee Hive',
  210. tiles = {"bees_hive_wild.png"}, --texture from church_candles.
  211. drawtype = "plantlike",
  212. paramtype = 'light',
  213. walkable = true,
  214. drop = {
  215. max_items = 6,
  216. items = {
  217. { items = {'bees:honeycomb'}, rarity = 5}
  218. }
  219. },
  220. groups = {choppy=2,oddly_breakable_by_hand=2,flammable=3,attached_node=1},
  221. on_timer = function(pos)
  222. local meta = minetest.get_meta(pos)
  223. local inv = meta:get_inventory()
  224. local timer= minetest.get_node_timer(pos)
  225. local rad = 10
  226. local minp = {x=pos.x-rad, y=pos.y-rad, z=pos.z-rad}
  227. local maxp = {x=pos.x+rad, y=pos.y+rad, z=pos.z+rad}
  228. local flowers = minetest.find_nodes_in_area(minp, maxp, 'group:flower')
  229. if #flowers == 0 then
  230. inv:set_stack('queen', 1, '')
  231. meta:set_string('infotext', 'This hive colony died! Not enough flowers in area.')
  232. return
  233. end --not any flowers nearby The queen dies!
  234. if #flowers < 3 then return end --requires 2 or more flowers before can make honey
  235. local flower = flowers[math.random(#flowers)]
  236. bees.polinate_flower(flower, minetest.get_node(flower).name)
  237. local stacks = inv:get_list('combs')
  238. for k, v in pairs(stacks) do
  239. if inv:get_stack('combs', k):is_empty() then --then replace that with a full one and reset pro..
  240. inv:set_stack('combs',k,'bees:honeycomb')
  241. timer:start(1000/#flowers)
  242. return
  243. end
  244. end
  245. --what to do if all combs are filled
  246. end,
  247. on_construct = function(pos)
  248. minetest.get_node(pos).param2 = 0
  249. local meta = minetest.get_meta(pos)
  250. local inv = meta:get_inventory()
  251. local timer = minetest.get_node_timer(pos)
  252. meta:set_int('agressive', 1)
  253. timer:start(100+math.random(100))
  254. inv:set_size('queen', 1)
  255. inv:set_size('combs', 5)
  256. inv:set_stack('queen', 1, 'bees:queen')
  257. for i=1,math.random(3) do
  258. inv:set_stack('combs', i, 'bees:honeycomb')
  259. end
  260. end,
  261. on_punch = function(pos, node, puncher)
  262. local meta = minetest.get_meta(pos)
  263. local inv = meta:get_inventory()
  264. if inv:contains_item('queen','bees:queen') then
  265. local health = puncher:get_hp()
  266. puncher:set_hp(health-4)
  267. end
  268. end,
  269. on_metadata_inventory_take = function(pos, listname, index, stack, taker)
  270. local meta = minetest.get_meta(pos)
  271. local inv = meta:get_inventory()
  272. local timer= minetest.get_node_timer(pos)
  273. if listname == 'combs' and inv:contains_item('queen', 'bees:queen') then
  274. local health = taker:get_hp()
  275. timer:start(10)
  276. taker:set_hp(health-2)
  277. end
  278. end,
  279. on_metadata_inventory_put = function(pos, listname, index, stack, taker) --restart the colony by adding a queen
  280. local timer = minetest.get_node_timer(pos)
  281. if not timer:is_started() then
  282. timer:start(10)
  283. end
  284. end,
  285. allow_metadata_inventory_put = function(pos, listname, index, stack, player)
  286. if listname == 'queen' and stack:get_name() == 'bees:queen' then
  287. return 1
  288. else
  289. return 0
  290. end
  291. end,
  292. on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
  293. minetest.show_formspec(
  294. clicker:get_player_name(),
  295. 'bees:hive_artificial',
  296. formspecs.hive_wild(pos, (itemstack:get_name() == 'bees:grafting_tool'))
  297. )
  298. local meta = minetest.get_meta(pos)
  299. local inv = meta:get_inventory()
  300. if meta:get_int('agressive') == 1 and inv:contains_item('queen', 'bees:queen') then
  301. local health = clicker:get_hp()
  302. clicker:set_hp(health-4)
  303. else
  304. meta:set_int('agressive', 1)
  305. end
  306. end,
  307. can_dig = function(pos,player)
  308. local meta = minetest.get_meta(pos)
  309. local inv = meta:get_inventory()
  310. if inv:is_empty('queen') and inv:is_empty('combs') then
  311. return true
  312. else
  313. return false
  314. end
  315. end,
  316. after_dig_node = function(pos, oldnode, oldmetadata, user)
  317. local wielded if user:get_wielded_item() ~= nil then wielded = user:get_wielded_item() else return end
  318. if 'bees:grafting_tool' == wielded:get_name() then
  319. local inv = user:get_inventory()
  320. if inv then
  321. inv:add_item('main', ItemStack('bees:queen'))
  322. end
  323. end
  324. end
  325. })
  326. minetest.register_node('bees:hive_artificial', {
  327. description = 'Bee Hive',
  328. tiles = {'default_wood.png','default_wood.png','default_wood.png', 'default_wood.png','default_wood.png','bees_hive_artificial.png'},
  329. drawtype = 'nodebox',
  330. paramtype = 'light',
  331. paramtype2 = 'facedir',
  332. groups = {snappy=1,choppy=2,oddly_breakable_by_hand=2,flammable=3,wood=1},
  333. sounds = default.node_sound_wood_defaults(),
  334. node_box = {
  335. type = 'fixed',
  336. fixed = {
  337. {-4/8, 2/8, -4/8, 4/8, 3/8, 4/8},
  338. {-3/8, -4/8, -2/8, 3/8, 2/8, 3/8},
  339. {-3/8, 0/8, -3/8, 3/8, 2/8, -2/8},
  340. {-3/8, -4/8, -3/8, 3/8, -1/8, -2/8},
  341. {-3/8, -1/8, -3/8, -1/8, 0/8, -2/8},
  342. {1/8, -1/8, -3/8, 3/8, 0/8, -2/8},
  343. }
  344. },
  345. on_construct = function(pos)
  346. local timer = minetest.get_node_timer(pos)
  347. local meta = minetest.get_meta(pos)
  348. local inv = meta:get_inventory()
  349. meta:set_int('agressive', 1)
  350. inv:set_size('queen', 1)
  351. inv:set_size('frames', 8)
  352. meta:set_string('infotext','Requires a queen bee to function.')
  353. end,
  354. on_rightclick = function(pos, node, clicker, itemstack)
  355. minetest.show_formspec(
  356. clicker:get_player_name(),
  357. 'bees:hive_artificial',
  358. formspecs.hive_artificial(pos)
  359. )
  360. local meta = minetest.get_meta(pos)
  361. local inv = meta:get_inventory()
  362. if meta:get_int('agressive') == 1 and inv:contains_item('queen', 'bees:queen') then
  363. local health = clicker:get_hp()
  364. clicker:set_hp(health-4)
  365. else
  366. meta:set_int('agressive', 1)
  367. end
  368. end,
  369. on_timer = function(pos,elapsed)
  370. local meta = minetest.get_meta(pos)
  371. local inv = meta:get_inventory()
  372. local timer = minetest.get_node_timer(pos)
  373. if inv:contains_item('queen', 'bees:queen') then
  374. if inv:contains_item('frames', 'bees:frame_empty') then
  375. timer:start(30)
  376. local rad = 10
  377. local minp = {x=pos.x-rad, y=pos.y-rad, z=pos.z-rad}
  378. local maxp = {x=pos.x+rad, y=pos.y+rad, z=pos.z+rad}
  379. local flowers = minetest.find_nodes_in_area(minp, maxp, 'group:flower')
  380. local progress = meta:get_int('progress')
  381. progress = progress + #flowers
  382. meta:set_int('progress', progress)
  383. if progress > 1000 then
  384. local flower = flowers[math.random(#flowers)]
  385. bees.polinate_flower(flower, minetest.get_node(flower).name)
  386. local stacks = inv:get_list('frames')
  387. for k, v in pairs(stacks) do
  388. if inv:get_stack('frames', k):get_name() == 'bees:frame_empty' then
  389. meta:set_int('progress', 0)
  390. inv:set_stack('frames',k,'bees:frame_full')
  391. return
  392. end
  393. end
  394. else
  395. meta:set_string('infotext', 'Progress: '..progress..'+'..#flowers..'/1000')
  396. end
  397. else
  398. meta:set_string('infotext', 'Hive does not have empty frame(s)!')
  399. timer:stop()
  400. end
  401. end
  402. end,
  403. on_metadata_inventory_take = function(pos, listname, index, stack, player)
  404. if listname == 'queen' then
  405. local timer = minetest.get_node_timer(pos)
  406. local meta = minetest.get_meta(pos)
  407. meta:set_string('infotext','Hive requires a queen bee to function!')
  408. timer:stop()
  409. end
  410. end,
  411. allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
  412. if minetest.is_protected(pos, player:get_player_name()) then
  413. return 0
  414. end
  415. local inv = minetest.get_meta(pos):get_inventory()
  416. if from_list == to_list then
  417. if inv:get_stack(to_list, to_index):is_empty() then
  418. return 1
  419. else
  420. return 0
  421. end
  422. else
  423. return 0
  424. end
  425. end,
  426. on_metadata_inventory_put = function(pos, listname, index, stack, player)
  427. local meta = minetest.get_meta(pos)
  428. local inv = meta:get_inventory()
  429. local timer = minetest.get_node_timer(pos)
  430. if listname == 'queen' or listname == 'frames' then
  431. meta:set_string('queen', stack:get_name())
  432. meta:set_string('infotext','A queen bee is inserted. Add empty frames!');
  433. if inv:contains_item('frames', 'bees:frame_empty') then
  434. timer:start(30)
  435. meta:set_string('infotext','Bees are settling in!');
  436. end
  437. end
  438. end,
  439. allow_metadata_inventory_put = function(pos, listname, index, stack, player)
  440. if minetest.is_protected(pos, player:get_player_name()) then
  441. return 0
  442. end
  443. if not minetest.get_meta(pos):get_inventory():get_stack(listname, index):is_empty() then return 0 end
  444. if listname == 'queen' then
  445. if stack:get_name():match('bees:queen*') then
  446. return 1
  447. end
  448. elseif listname == 'frames' then
  449. if stack:get_name() == ('bees:frame_empty') then
  450. return 1
  451. end
  452. end
  453. return 0
  454. end,
  455. allow_metadata_inventory_take = function(pos, listname, index, stack, player)
  456. if minetest.is_protected(pos,player:get_player_name()) then
  457. return 0
  458. end
  459. return stack:get_count()
  460. end,
  461. })
  462. --ABMS
  463. minetest.register_abm({ --particles
  464. nodenames = {'bees:hive_artificial', 'bees:hive_wild'},
  465. interval = 10,
  466. chance = 4,
  467. action = function(pos)
  468. minetest.add_particle({
  469. pos = {x=pos.x, y=pos.y, z=pos.z},
  470. vel = {x=(math.random()-0.5)*5,y=(math.random()-0.5)*5,z=(math.random()-0.5)*5},
  471. acc = {x=math.random()-0.5,y=math.random()-0.5,z=math.random()-0.5},
  472. expirationtime = math.random(2.5),
  473. size = math.random(3),
  474. collisiondetection = true,
  475. texture = 'bees_particle_bee.png',
  476. })
  477. end,
  478. })
  479. minetest.register_abm({ --spawn abm. This should be changed to a more realistic type of spawning
  480. nodenames = {'group:leaves'},
  481. interval = 1600,
  482. chance = 20,
  483. action = function(pos, node)
  484. local p = {x=pos.x, y=pos.y-1, z=pos.z}
  485. if minetest.get_node(pos).walkable == false then return end
  486. if (minetest.find_node_near(p, 5, 'group:flower') ~= nil and minetest.find_node_near(p, 40, 'bees:hive_wild') == nil) then
  487. minetest.add_node(p, {name='bees:hive_wild'})
  488. minetest.sound_play({name = "bees", gain = 1.0}, {pos=p, max_hear_distance = 8})
  489. end
  490. end,
  491. })
  492. minetest.register_abm({ --spawning bees around bee hive
  493. nodenames = {'bees:hive_wild', 'bees:hive_artificial'},
  494. neighbors = {'group:flower', 'group:leaves'},
  495. interval = 30,
  496. chance = 4,
  497. action = function(pos, node, _, _)
  498. local p = {x=pos.x+math.random(-5,5), y=pos.y-math.random(0,3), z=pos.z+math.random(-5,5)}
  499. if minetest.get_node(p).name == 'air' then
  500. minetest.add_node(p, {name='bees:bees'})
  501. minetest.sound_play({name = "bees", gain = 1.0}, {pos=p, max_hear_distance = 8})
  502. end
  503. end,
  504. })
  505. minetest.register_abm({ --remove bees
  506. nodenames = {'bees:bees'},
  507. interval = 30,
  508. chance = 5,
  509. action = function(pos, node, _, _)
  510. minetest.remove_node(pos)
  511. end,
  512. })
  513. -- Load other modules for the mod.
  514. local default_path = minetest.get_modpath("bees")
  515. dofile(default_path.."/crafting.lua")
  516. dofile(default_path.."/craftitems.lua")
  517. dofile(default_path.."/nodes.lua")
  518. dofile(default_path.."/tools.lua")