How to identify ground level (or treetop level)

dgm5555
Member
 
Posts: 245
Joined: Tue Apr 08, 2014 19:45

How to identify ground level (or treetop level)

by dgm5555 » Mon May 12, 2014 23:18

EDIT: The following code seems to work correctly:-
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)
Last edited by dgm5555 on Thu May 22, 2014 19:25, edited 1 time in total.
 

User avatar
Calinou
Moderator
 
Posts: 3159
Joined: Mon Aug 01, 2011 14:26
Location: Troyes, France
GitHub: Calinou
IRC: Calinou
In-game: Calinou

Re: How to identify ground level (or treetop level)

by Calinou » Tue May 13, 2014 12:28

I can't help much, but for consistency, variables should be like_this, not likeThis.
 

User avatar
Evergreen
Member
 
Posts: 2135
Joined: Sun Jan 06, 2013 01:22
Location: A forest in the midwest
GitHub: 4Evergreen4
IRC: EvergreenTree
In-game: Evergreen

Re: How to identify ground level (or treetop level)

by Evergreen » Tue May 13, 2014 12:36

Calinou wrote:I can't help much, but for consistency, variables should be like_this, not likeThis.

True, camelcase is not what we use around here. :P
 

spillz
Member
 
Posts: 138
Joined: Thu Feb 13, 2014 05:11

Re: How to identify ground level (or treetop level)

by spillz » Tue May 13, 2014 13:00

I don't think he asked for style pointers. Sheesh. (And the engine is littered with camelCase last I checked)

What are you trying to do dgm? From what I understand the engine wasn't designed to handle having arbitrary sections of the map loaded, but there was talk on IRC a month ago about improving this situation (and i think some code exists)
 

User avatar
Calinou
Moderator
 
Posts: 3159
Joined: Mon Aug 01, 2011 14:26
Location: Troyes, France
GitHub: Calinou
IRC: Calinou
In-game: Calinou

Re: How to identify ground level (or treetop level)

by Calinou » Tue May 13, 2014 13:39

spillz wrote:I don't think he asked for style pointers. Sheesh. (And the engine is littered with camelCase last I checked)


Those are not supposed to be there (and are likely from external contributors). On the old wiki, celeron55 specifically wrote the variables should be like_this and not likeThis.

The default mods also use a similar variable styling.

If you want to continue the discussion, I suggest PMing me or creating a new topic. Let's stay on-topic here, thanks in advance. :)
 

dgm5555
Member
 
Posts: 245
Joined: Tue Apr 08, 2014 19:45

Re: How to identify ground level (or treetop level)

by dgm5555 » Tue May 13, 2014 14:23

sorry about the camel case, I picked it up many years ago as it was a little more concise, and found that trying to switch back and forth made my own code inconsistent, which was even worse than being different to the current flavour of the project, should it become critical I can easily change them all with a script.

The projects I'm working on which use ground level are mapping the world and placing random items and teleporting to locations without using pre-defined destinations. I'd also like to generate some buildings/features randomly, but don't want to do it in areas a player has already visited (like happen to me recently when something (paragenv7?) randomly decided to cover what was previously an empty patch of desert in jungle trees with a number of them floating above the ground). Ground level is my biggest frustration, but also I can't find any exposed functions which tell me if a block of nodes has been generated, or where the x and z boundaries of the currently generated world are, or force generation without a player trigger. Teleporting a player to an area either forces generation or loads the block (but I can't tell which, so don't know if I should put stuff there) and when this has completed enables me to find ground level. However as I mentioned moving the player around doesn't seem like a very elegant solution. Intuitively it feels like these basic functions would have been exposed, but I can't find them, so am trying to make what I can...
Last edited by dgm5555 on Tue May 13, 2014 18:50, edited 2 times in total.
 

Kodiologist
Member
 
Posts: 13
Joined: Fri Dec 27, 2013 18:06

Re: How to identify ground level (or treetop level)

by Kodiologist » Tue May 13, 2014 15:31

See this thread for a previous discussion. But, as you can see, I ended up using the light level, too.
 

User avatar
HeroOfTheWinds
Member
 
Posts: 470
Joined: Wed Apr 23, 2014 23:16
Location: Hawaii
GitHub: HeroOfTheWinds
IRC: WindHero

Re: How to identify ground level (or treetop level)

by HeroOfTheWinds » Tue May 13, 2014 20:40

Unless you absolutely need to have this code occur in places before you get to them, I highly recommend using the minetest.register_on_generated() function. Then, whenever the player reaches a new chunk, it will call whatever code you have in that function. Now, as for finding ground level. One method is to use the voxelmanip to loop through xyz values from the top down, and upon finding a node ~= "air", call your ground level code. Take a look at paramat's highlandpools mod for an example of this.

I'd say this is the most balanced solution between elegance, speed, and control, but I could be wrong. There's no need to displace a player just to generate something ahead of time. That will only eat up hard drive space on servers where no one may ever even visit a chunk that was loaded for no good reason.
Nam ex spatio, omnes res venire possunt.
Why let the ground limit you when you can reach for the sky?
Back to college now, yay for sophomore year schedules. :P
 

User avatar
Topywo
Member
 
Posts: 1721
Joined: Fri May 18, 2012 20:27

Re: How to identify ground level (or treetop level)

by Topywo » Wed May 14, 2014 09:28

I don't know if this is of any use at all.

The ore generation in default/mapgen.lua gives the possibility to generate nodes you create at random positions, for which you can specifiy the height.

Example:
Code: Select all
minetest.register_ore({
   ore_type       = "scatter",
   ore            = "default:stone_with_coal",
   wherein        = "default:stone",
   clust_scarcity = 8*8*8,
   clust_num_ores = 8,
   clust_size     = 3,
   height_min     = -31000,
   height_max     = 64,
})


What you can do is something like this:
Code: Select all
minetest.register_ore({
   ore_type       = "scatter",
   ore            = "mymod:fakeairorwhatever",
   wherein        = "air",
   clust_scarcity = 8*8*8,
   clust_num_ores = 8,
   clust_size     = 3,
   height_min     = 0,
   height_max     = 1,
})
 

User avatar
paramat
Developer
 
Posts: 3560
Joined: Sun Oct 28, 2012 00:05
Location: UK
GitHub: paramat
IRC: paramat

Re: How to identify ground level (or treetop level)

by paramat » Wed May 14, 2014 22:07

It is possible to know ground level at any co-ordinate in advance of map generation, but i think the only way is to recreate the mapgen in lua. My 'spawn player' functions in watershed and fracture do this to spawn the player at the correct height to avoid burial or falling to death. But then it's easy for me to recreate my mapgen code within a function.
It would be good to recreate mgv6, useful for re-generating chunks too.
 

dgm5555
Member
 
Posts: 245
Joined: Tue Apr 08, 2014 19:45

Re: How to identify ground level (or treetop level)

by dgm5555 » Wed May 14, 2014 22:50

paramat wrote:It is possible to know ground level at any co-ordinate in advance of map generation, but i think the only way is to recreate the mapgen in lua.

This looks like a good method, actually if it's that simple it's even more surprising minetest doesn't expose the function, I guess I'd still have to check for trees etc, but at least I won't be starting far from ground. Does the mapgen version not have to be coded for?
 

dgm5555
Member
 
Posts: 245
Joined: Tue Apr 08, 2014 19:45

Re: How to identify ground level (or treetop level)

by dgm5555 » Sat May 17, 2014 08:46

I have tried lots of different methods, and it seems that there is no method to force the engine to load a block other than moving a player to the spot and leaving them there after the function exits.
I've tried light levels, loops, forceload, sleep commands, placing nodes, more loops, etc, etc...
This code seems to work best
Code: Select all
teleportTargetWuX = pngMinWuX + butX*worldStepWuX + 0.5*worldStepWuX
teleportTargetWuZ = pngMaxWuZ - butZ*worldStepWuZ - 0.5*worldStepWuZ
local groundLevel = nil
local i
for i = 96, 0, -1 do   
   p = {x=teleportTargetWuX, y=i, z=teleportTargetWuZ}
   player:setpos(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
   print("Mapit Teleport Successful")
   player:setpos({x=teleportTargetWuX, y=groundLevel, z=teleportTargetWuZ})
else
   -- minetest failed to load the block within the loop, and never seems to no matter how many loops are executed
   --   (even os.execute("sleep 10") doesn't give it time to do so)
   -- However completing the function and having the player re-activate it seems to trigger the engine to load properly
   -- Don't set player back to departure position, or the block will never be loaded
   minetest.chat_send_player(mapItPlayerName, "mapit: Aaarrrgh Teleport Mistargeted (Please Try Again)", false)
end
 

User avatar
BrandonReese
Member
 
Posts: 839
Joined: Wed Sep 12, 2012 00:44
Location: USA
GitHub: bremaweb
IRC: BrandonReese
In-game: BrandonReese

Re: How to identify ground level (or treetop level)

by BrandonReese » Sat May 17, 2014 14:30

I'm pretty sure you can force an area to load with voxelmanip. I've never used it before but I believe that's how the Technic quarries quarry down 100 nodes from the source without a player present. I think it will even force mapgen to run when you access an area of the map that hasn't been generated.
 

User avatar
Hybrid Dog
Member
 
Posts: 2728
Joined: Thu Nov 01, 2012 12:46

Re: How to identify ground level (or treetop level)

by Hybrid Dog » Sat May 17, 2014 15:01

̣
Last edited by Hybrid Dog on Thu May 22, 2014 17:36, edited 1 time in total.

‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪
 

dgm5555
Member
 
Posts: 245
Joined: Tue Apr 08, 2014 19:45

Re: How to identify ground level (or treetop level)

by dgm5555 » Sun May 18, 2014 09:31

I tried forceload_block, it didn't seem to work while the call to the function was running even with long sleeps and/or loops to delay. might look at technic and try voxelmanip.
 

User avatar
Hybrid Dog
Member
 
Posts: 2728
Joined: Thu Nov 01, 2012 12:46

Re: How to identify ground level (or treetop level)

by Hybrid Dog » Sun May 18, 2014 13:35

̣

‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪‮
‮‪
 

dgm5555
Member
 
Posts: 245
Joined: Tue Apr 08, 2014 19:45

Re: How to identify ground level (or treetop level)

by dgm5555 » Thu May 22, 2014 19:18

voxel_manip seems to force the loading of the block, so a groundlevel search works. I've changed the code in the first post to provided the entire loop to find ground level...
Code: Select all
local manip = minetest.get_voxel_manip()
p = {x=targetX, y=i, z=targetZ}
manip:read_from_map(p, p)
 

Smitje
Member
 
Posts: 22
Joined: Wed Nov 14, 2012 20:42

Re: How to identify ground level (or treetop level)

by Smitje » Mon Aug 18, 2014 18:45

It depeds if you are using mapgen v6 or v7.

This is what I just learned from paramat:
by paramat » Mon Aug 18, 2014 6:49 am
https://github.com/minetest/minetest/bl ... .txt#L2126 line 2126
Not sure if all of these are available within mapgen v6, some may be v7 only.


I checked and the following only works in v7 not in v6:
Code: Select all
lastheightmap = minetest.get_mapgen_object("heightmap")


alternatively, mapgen.cpp uses a function that checks for the highest node that is walkable:
lines 921 to 937
perhaps this could be recreated in LUA

cheers,
Smitje
 

Smitje
Member
 
Posts: 22
Joined: Wed Nov 14, 2012 20:42

Re: How to identify ground level (or treetop level)

by Smitje » Sat Sep 06, 2014 21:25

Hi all,

I did a little hacking to make the groundlevel available in my own mod it may be usefull. see this thread:
viewtopic.php?f=7&t=9940

Cheers,
Smitje
 


Return to WIP Mods



Who is online

Users browsing this forum: No registered users and 7 guests