123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- if not minetest.global_exists("papyrus") then papyrus = {} end
- papyrus.modpath = minetest.get_modpath("default")
- papyrus.steptime = {min=60*5, max=60*20}
- papyrus.plantname = "default:papyrus"
- papyrus.maxheight = 5
- papyrus.minlight = 13
- -- Localize for performance.
- local math_floor = math.floor
- local math_random = math.random
- function papyrus.on_place(itemstack, placer, pt)
- local under = pt.under
- local above = pt.above
- local node = minetest.get_node(under)
- local ndef = minetest.registered_nodes[node.name]
- -- Call on_rightclick if target node defines it.
- if ndef and ndef.on_rightclick and
- ((not placer) or (placer and not placer:get_player_control().sneak)) then
- return ndef.on_rightclick(under, node, placer, itemstack, pt) or itemstack
- end
- local fakestack = itemstack
- -- Pointing at bottom face? Place hanging papyrus.
- if above.y == (under.y - 1) then
- --minetest.chat_send_all('placing hanging variant')
- fakestack = ItemStack("default:papyrus2")
- fakestack:set_count(itemstack:get_count())
- end
- local stack, success, pos = minetest.item_place_node(fakestack, placer, pt)
- if success then
- itemstack:set_count(stack:get_count())
- return itemstack
- end
- end
- -- Should return a random height for an individual plant to grow.
- function papyrus.random_height()
- return math_floor(math_random(math_random(2, 3), math_random(3, 5)))
- end
- function papyrus.is_dirt_name(name)
- if name == "default:dirt_with_grass" or name == "default:dirt" or name == "moregrass:darkgrass" then
- return true
- end
- end
- function papyrus.has_dirt(pos)
- local p = vector.add(pos, {x=0, y=-1, z=0})
- local name = minetest.get_node(p).name
- -- Must be on dirt or grass.
- if papyrus.is_dirt_name(name) then
- return true
- end
- end
- function papyrus.can_grow(pos)
- -- Must have dirt nearby.
- if not papyrus.has_dirt(pos) then
- return
- end
- -- Must have water nearby.
- local p = vector.add(pos, {x=0, y=-1, z=0})
- if not minetest.find_node_near(p, 3, {"group:water"}) then
- return
- end
- return true
- end
- -- Obtain growth height from soil, initializing it if not done yet.
- function papyrus.get_grow_height(pos)
- local meta = minetest.get_meta({x=pos.x, y=pos.y-1, z=pos.z})
- local maxh = meta:get_int("papyrus_height")
- if maxh == 0 then
- maxh = papyrus.random_height()
- meta:set_int("papyrus_height", maxh)
- meta:mark_as_private("papyrus_height")
- end
- return maxh
- end
- -- Should be called when plant is dug.
- function papyrus.reset_grow_height_and_timer(pos)
- -- Find soil node below plant.
- local p = vector.new(pos)
- local name = minetest.get_node(p).name
- local d = 0
- while not papyrus.is_dirt_name(name) and d < papyrus.maxheight do
- -- All except bottom-most node must be plant.
- if name ~= papyrus.plantname then
- return
- end
- p.y = p.y - 1
- d = d + 1
- name = minetest.get_node(p).name
- end
- -- Must be on dirt or grass.
- if papyrus.is_dirt_name(name) then
- local meta = minetest.get_meta(p)
- local maxh = papyrus.random_height()
- meta:set_int("papyrus_height", maxh)
- meta:mark_as_private("papyrus_height")
- else
- return
- end
- -- Restart timer for plant directly above soil.
- p.y = p.y + 1
- if minetest.get_node(p).name ~= papyrus.plantname then
- return
- end
- local min = papyrus.steptime.min
- local max = papyrus.steptime.max
- minetest.get_node_timer(p):start(math_random(min, max))
- end
- -- Attempt to grow papyrus.
- -- Return 0 means nothing to report.
- -- 10 means plant has reached max height.
- function papyrus.grow(pos, node)
- -- Check if we can grow.
- if not papyrus.can_grow(pos) then
- return 0
- end
- if minetest.find_node_near(pos, 2, "group:cold") then
- return 12
- end
- -- Get how high we can grow.
- local maxh = papyrus.get_grow_height(pos)
- -- Find current height of plant.
- local height = 0
- while node.name == papyrus.plantname and height < maxh do
- height = height + 1
- pos.y = pos.y + 1
- node = minetest.get_node(pos)
- end
- if height >= maxh then
- -- Plant has reached max height.
- return 10
- end
- -- Check if we have room to grow some more.
- if node.name ~= "air" then
- return 0
- end
- -- Check if we have enough light.
- if minetest.get_node_light(pos) < papyrus.minlight then
- return 0
- end
- -- Grow!
- minetest.add_node(pos, {name = papyrus.plantname})
- return 0
- end
- function papyrus.on_construct(pos)
- -- Only the ground-level plant piece should have nodetimer.
- -- If plant is not placed on soil, it will never have nodetimer.
- if papyrus.has_dirt(pos) then
- local min = papyrus.steptime.min
- local max = papyrus.steptime.max
- minetest.get_node_timer(pos):start(math_random(min, max))
- end
- end
- function papyrus.on_destruct(pos)
- papyrus.reset_grow_height_and_timer(pos)
- end
- function papyrus.on_timer(pos, elapsed)
- --minetest.chat_send_all("# Server: Plant timer @ " .. minetest.pos_to_string(pos) .. "!")
- local node = minetest.get_node(pos)
- local result = papyrus.grow(pos, node)
- -- Plant has reached max height.
- if result == 10 then return end
- -- Plant cannot grow because of ice.
- if result == 12 then return end
- return true
- end
- function papyrus.after_dig_node(pos, node, metadata, digger)
- default.dig_up(pos, node, digger)
- -- No return value.
- end
- function papyrus.after_dig_node_hanging(pos, node, metadata, digger)
- default.dig_down(pos, node, digger)
- -- No return value.
- end
- if not papyrus.run_once then
- local c = "papyrus:core"
- local f = papyrus.modpath .. "/papyrus.lua"
- reload.register_file(c, f, false)
- papyrus.run_once = true
- end
|