Place node once per mapchunk

User avatar
texmex
Member
 
Posts: 1616
Joined: Mon Jul 11, 2016 21:08
GitHub: tacotexmex
In-game: texmex

Place node once per mapchunk

by texmex » Sun Nov 24, 2019 10:03

I want to place a node (at the most) once per mapchunk, on surfaces. I imagine voxelmanip needs to be involved. How do I do it?

I've tried to find examples but they all relate to mapblocks, not mapchunks.
Last edited by texmex on Tue Nov 26, 2019 23:13, edited 2 times in total.
 

User avatar
rubenwardy
Moderator
 
Posts: 5886
Joined: Tue Jun 12, 2012 18:11
Location: United Kingdom
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy

Re: Place node once per mapchunk

by rubenwardy » Sun Nov 24, 2019 12:27

Use on generated, and then choose a random position within that range. You'll need to use the map gen lvm otherwise your change will be reverted


(Just incase you're using the wrong term: Chunk = 5*5*5 Blocks = 80*80*80 Nodes)
 

User avatar
texmex
Member
 
Posts: 1616
Joined: Mon Jul 11, 2016 21:08
GitHub: tacotexmex
In-game: texmex
 

Sokomine
Member
 
Posts: 3913
Joined: Sun Sep 09, 2012 17:31
GitHub: Sokomine

Re: Place node once per mapchunk

by Sokomine » Sun Nov 24, 2019 18:27

If it's just a single node and if it's placed in the center of the mapchunk, a simple set_node might be more than enough. The heightmap can help at locating ground surface. Places at the border may also work as long as the node has is_ground_content = false set (else cavegen might grief it).
A list of my mods can be found here.
 

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

Re: Place node once per mapchunk

by paramat » Sun Nov 24, 2019 18:51

No need to use the Lua Voxel Manipulator. For placing 1 node 'set_node()' is much faster.

In 'minetest.register_on_generated(function(minp, maxp, seed) ... end)', choose random x and z coords within the minp-maxp area, calculate the heightmap index for that column, get the surface y from the heightmap, and place the node there.
 

User avatar
rubenwardy
Moderator
 
Posts: 5886
Joined: Tue Jun 12, 2012 18:11
Location: United Kingdom
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy

Re: Place node once per mapchunk

by rubenwardy » Sun Nov 24, 2019 19:22

paramat wrote:No need to use the Lua Voxel Manipulator. For placing 1 node 'set_node()' is much faster.


Don't you need to use the mapgen lvm to prevent the mapgen from overwriting your changes?
 

User avatar
texmex
Member
 
Posts: 1616
Joined: Mon Jul 11, 2016 21:08
GitHub: tacotexmex
In-game: texmex

Re: Place node once per mapchunk

by texmex » Sun Nov 24, 2019 21:09

I tried this:
Code: Select all
minetest.register_on_generated(function(minp, maxp, seed)
   if maxp.y < 1 then return end

   local nodes = minetest.find_nodes_in_area_under_air(minp, maxp, "group:grass")

   if not nodes[1] then return end

   math.randomseed(seed)
   local chance = math.random(1, 10)
   if not chance == 1 then return end

   local node = nodes[math.random(1, #nodes)]
   local pos = vector.add(node, {x=0, y=10, z=0})

   minetest.log("action", "Placed node at " .. minetest.pos_to_string(pos))

   minetest.set_node(pos, {name = "lanterns:paper_lantern"})
end)


How do I get the surface pos from the heightmap?
 

Sokomine
Member
 
Posts: 3913
Joined: Sun Sep 09, 2012 17:31
GitHub: Sokomine

Re: Place node once per mapchunk

by Sokomine » Sun Nov 24, 2019 21:19

texmex wrote:local nodes = minetest.find_nodes_in_area_under_air(minp, maxp, "group:grass")

Er...probably a bit too many. That's a large array and may be expensive to get if it's over the entire mapchunk...

Get the heightmap:
Code: Select all
local heightmap = minetest.get_mapgen_object('heightmap')

Then determine a random x and z position withhin minp.x, maxp.x and minp.z, maxp.z. And get the height at your choosen position:
Code: Select all
local chunksize =  maxp.x - minp.x + 1;
local h = heightmap[((z-minp.z)*chunksize) + (x-minp.x)]

If h is nil, lower than minp.y or higher than maxp.y, then there's no ground level inside this mapchunk at this position (probably a mountain or a deep hole). Choose other x and z coordinates and try with them. Once you found a position, you may place your node at x, h, z.
A list of my mods can be found here.
 

User avatar
texmex
Member
 
Posts: 1616
Joined: Mon Jul 11, 2016 21:08
GitHub: tacotexmex
In-game: texmex

Re: Place node once per mapchunk

by texmex » Sun Nov 24, 2019 21:54

Thanks Sokomine, I’ll look into it. So that’s how one uses the heightmap… very useful!
 

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

Re: Place node once per mapchunk

by paramat » Mon Nov 25, 2019 20:01

rubenwardy wrote:Don't you need to use the mapgen lvm to prevent the mapgen from overwriting your changes?

No need. Anything in 'on generated' runs after all engine mapgen finishes. The only way your changes can be overwritten is in the edge mapblocks, by the overgeneration of structures (randomwalk caves, dungeons or decorations) from neighbour mapchunks that generate later.

Maybe you are thinking of the situation where mapchunk data is loaded into the LVM, then 'set node' is used, then the LVM is written to the map not including the 'set node' change?

> That's a large array and may be expensive to get if it's over the entire mapchunk...

Correct, do not use a search that big.
 

User avatar
rubenwardy
Moderator
 
Posts: 5886
Joined: Tue Jun 12, 2012 18:11
Location: United Kingdom
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy

Re: Place node once per mapchunk

by rubenwardy » Mon Nov 25, 2019 20:46

Ah, set_node is clever enough to update the mapgen's Lua Voxel Manipulator:

The `on_generated()` callbacks of some mods may place individual nodes in the generated area using non-VoxelManip map modification methods. Because the same Mapgen VoxelManip object is passed through each `on_generated()` callback, it becomes necessary for the Mapgen VoxelManip object to maintain consistency with the current map state. For this reason, calling any of the following functions: `minetest.add_node()`, `minetest.set_node()`, or `minetest.swap_node()` will also update the Mapgen VoxelManip object's internal state active on the current thread.
 

User avatar
texmex
Member
 
Posts: 1616
Joined: Mon Jul 11, 2016 21:08
GitHub: tacotexmex
In-game: texmex

Re: Place node once per mapchunk

by texmex » Tue Nov 26, 2019 23:05

Turns out tsm_surprise has some valuabe code that can be used, though it doesn't make that slick use of the heightmap.
 


Return to Modding Discussion



Who is online

Users browsing this forum: TenPlus1 and 2 guests