Code: Select all
local function groundLevel(targetX,targetZ)
local manip = minetest.get_voxel_manip() -- the voxel_manip is require to force loading of the block
local groundLevel = nil
local i
-- This will fail if ground level is 100 or above or below below -100 (but this doesn't happen very often)
for i = 96, -100, -1 do
p = {x=targetX, y=i, z=targetZ}
manip:read_from_map(p, p)
if minetest.get_node(p).name ~= "air" and minetest.get_node(p).name ~= "ignore" then
groundLevel = i
break
end
end
if groundLevel ~= nil then
-- Search Successful
return {x=targetX, y=groundLevel, z=targetZ}
else
-- Search Failed
print("groundLevel Search Failed. Groundlevel could be deeper than -100")
return -1
end
end
The following is the original post which stimulated the discussion:-
Is there a better way than this to identify ground level in an area which hasn't been visited recently?
My code works but isn't very elegant, as nodes are all seem to be named "ignore" or have a light level of nil unless a player has recently been near them. Moving the player temporarily to the area seems to work as I presume it forces minetest to load the block, but it doesn't seem very elegant. It also forces minetest to generate the terrain even if the area has never been visited, which isn't necesarily desirable. The loop also needs to be repeated as it fails on the initial cycle (presumably loading is slower than looking for nodes). In the forums is mentioned a lua function get_ground_level, but I couldn't find it in the api. minetest.forceload_block(pos) also seems to be slow, but I read somewhere it forces minetest to load it at future startups too, which I don't want.
Code: Select all
local curPos = player:getpos()
local i
while groundLevel == nil do
for i = 100, -100, -1 do
local p = {x=worldX, y=i, z=worldZ}
player:setpos(p)
-- print (minetest.get_node_light(p, 0.5))
-- print (minetest.get_node(p).name)
if minetest.get_node(p).name ~= "air" and minetest.get_node(p).name ~= "ignore" then
groundLevel = i
break
end
end
end
player:setpos(curPos)