papyrus.lua 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. papyrus = papyrus or {}
  2. papyrus.modpath = minetest.get_modpath("default")
  3. papyrus.steptime = {min=60*5, max=60*20}
  4. papyrus.plantname = "default:papyrus"
  5. papyrus.maxheight = 5
  6. papyrus.minlight = 13
  7. -- Should return a random height for an individual plant to grow.
  8. function papyrus.random_height()
  9. return math.floor(math.random(math.random(2, 3), math.random(3, 5)))
  10. end
  11. function papyrus.is_dirt_name(name)
  12. if name == "default:dirt_with_grass" or name == "default:dirt" or name == "moregrass:darkgrass" then
  13. return true
  14. end
  15. end
  16. function papyrus.has_dirt(pos)
  17. local p = vector.add(pos, {x=0, y=-1, z=0})
  18. local name = minetest.get_node(p).name
  19. -- Must be on dirt or grass.
  20. if papyrus.is_dirt_name(name) then
  21. return true
  22. end
  23. end
  24. function papyrus.can_grow(pos)
  25. -- Must have dirt nearby.
  26. if not papyrus.has_dirt(pos) then
  27. return
  28. end
  29. -- Must have water nearby.
  30. local p = vector.add(pos, {x=0, y=-1, z=0})
  31. if not minetest.find_node_near(p, 3, {"group:water"}) then
  32. return
  33. end
  34. return true
  35. end
  36. -- Obtain growth height from soil, initializing it if not done yet.
  37. function papyrus.get_grow_height(pos)
  38. local meta = minetest.get_meta({x=pos.x, y=pos.y-1, z=pos.z})
  39. local maxh = meta:get_int("papyrus_height")
  40. if maxh == 0 then
  41. maxh = papyrus.random_height()
  42. meta:set_int("papyrus_height", maxh)
  43. end
  44. return maxh
  45. end
  46. -- Should be called when plant is dug.
  47. function papyrus.reset_grow_height_and_timer(pos)
  48. -- Find soil node below plant.
  49. local p = vector.new(pos)
  50. local name = minetest.get_node(p).name
  51. local d = 0
  52. while not papyrus.is_dirt_name(name) and d < papyrus.maxheight do
  53. -- All except bottom-most node must be plant.
  54. if name ~= papyrus.plantname then
  55. return
  56. end
  57. p.y = p.y - 1
  58. d = d + 1
  59. name = minetest.get_node(p).name
  60. end
  61. -- Must be on dirt or grass.
  62. if papyrus.is_dirt_name(name) then
  63. local meta = minetest.get_meta(p)
  64. local maxh = papyrus.random_height()
  65. meta:set_int("papyrus_height", maxh)
  66. else
  67. return
  68. end
  69. -- Restart timer for plant directly above soil.
  70. p.y = p.y + 1
  71. if minetest.get_node(p).name ~= papyrus.plantname then
  72. return
  73. end
  74. local min = papyrus.steptime.min
  75. local max = papyrus.steptime.max
  76. minetest.get_node_timer(p):start(math.random(min, max))
  77. end
  78. -- Attempt to grow papyrus.
  79. -- Return 0 means nothing to report.
  80. -- 10 means plant has reached max height.
  81. function papyrus.grow(pos, node)
  82. -- Check if we can grow.
  83. if not papyrus.can_grow(pos) then
  84. return 0
  85. end
  86. if minetest.find_node_near(pos, 2, "group:cold") then
  87. return 12
  88. end
  89. -- Get how high we can grow.
  90. local maxh = papyrus.get_grow_height(pos)
  91. -- Find current height of plant.
  92. local height = 0
  93. while node.name == papyrus.plantname and height < maxh do
  94. height = height + 1
  95. pos.y = pos.y + 1
  96. node = minetest.get_node(pos)
  97. end
  98. if height >= maxh then
  99. -- Plant has reached max height.
  100. return 10
  101. end
  102. -- Check if we have room to grow some more.
  103. if node.name ~= "air" then
  104. return 0
  105. end
  106. -- Check if we have enough light.
  107. if minetest.get_node_light(pos) < papyrus.minlight then
  108. return 0
  109. end
  110. -- Grow!
  111. minetest.add_node(pos, {name = papyrus.plantname})
  112. return 0
  113. end
  114. function papyrus.on_construct(pos)
  115. -- Only the ground-level plant piece should have nodetimer.
  116. -- If plant is not placed on soil, it will never have nodetimer.
  117. if papyrus.has_dirt(pos) then
  118. local min = papyrus.steptime.min
  119. local max = papyrus.steptime.max
  120. minetest.get_node_timer(pos):start(math.random(min, max))
  121. end
  122. end
  123. function papyrus.on_destruct(pos)
  124. papyrus.reset_grow_height_and_timer(pos)
  125. end
  126. function papyrus.on_timer(pos, elapsed)
  127. --minetest.chat_send_all("# Server: Plant timer @ " .. minetest.pos_to_string(pos) .. "!")
  128. local node = minetest.get_node(pos)
  129. local result = papyrus.grow(pos, node)
  130. -- Plant has reached max height.
  131. if result == 10 then return end
  132. -- Plant cannot grow because of ice.
  133. if result == 12 then return end
  134. return true
  135. end
  136. function papyrus.after_dig_node(pos, node, metadata, digger)
  137. default.dig_up(pos, node, digger)
  138. -- No return value.
  139. end
  140. if not papyrus.run_once then
  141. local c = "papyrus:core"
  142. local f = papyrus.modpath .. "/papyrus.lua"
  143. reload.register_file(c, f, false)
  144. papyrus.run_once = true
  145. end