TenPlus1 wrote:Could you please move my "Lucky Block" mod to MOD Releases :) Thanks...
viewtopic.php?f=9&t=13284
...and also my Pie mod also...
viewtopic.php?f=9&t=13285
Sane wrote:...
I have noticed that the function registered with minetest.register_on_generated gets called more than once. That seems a bit odd to me.
...
Don wrote:I want to place a block every 1000 nodes square. It should be somewhat random. I do not want it to be exactly 1000.
The node will be placed in water on mapgen at surface height.
I am not great with mapgen and was wondering what the best way to do this is?
Sane wrote:Don wrote:New world
ArguablySane has posted a solution:
viewtopic.php?f=3&t=13132&p=191868#p189480
Don wrote:Sane wrote:Don wrote:New world
ArguablySane has posted a solution:
viewtopic.php?f=3&t=13132&p=191868#p189480
Thanks. I will try to modify it to make it work. Do you know if this works with all mapgens or just v5 and v7?
--[[
Node placer - Places a node on the surface, at a random position in the mg block that contains a grid point defined by cell_size
published under Creative Commons CC0 license.
--]]
-- cell_size must be bigger then mg block size (80) to work.
local cell_size = 150
local item_id = minetest.get_content_id("default:steelblock")
minetest.register_on_generated(function(minp, maxp, seed)
-- If the next_hotspot is not within this mg block then exit
local next_hotspot = {
x = math.ceil(minp.x / cell_size) * cell_size,
y = math.ceil(minp.y / cell_size) * cell_size,
z = math.ceil(minp.z / cell_size) * cell_size
}
if next_hotspot.x > maxp.x or
next_hotspot.y > maxp.y or
next_hotspot.z > maxp.z then return end
-- Place the object somewhere in this block
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local va = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
local vd = vm:get_data()
local r = PcgRandom(seed) -- this ensures that you get the same results each time you generate the world anew.
local item_pos = {
x = r:next(minp.x, maxp.x),
y = r:next(minp.y, maxp.y),
z = r:next(minp.z, maxp.z),
}
-- This is to optimize, because getting the height map is expensive
if minp.y > -200 and maxp.y < 200 then
local hm = minetest.get_mapgen_object("heightmap")
local hz = (item_pos.z - minp.z) * 80
local hx = (item_pos.x - minp.x) % 80
local height = hm[1 + hx + hz]
item_pos.y = height + 1
end
vd[va:indexp(item_pos)] = item_id
--
vm:set_data(vd)
--vm:calc_lighting()
--vm:update_liquids()
vm:write_to_map()
--vm:update_map()
--
end)
Don wrote:I have another issue though. I have a mts schematic that contains a node with a formspec. When the schematic is placed the node does not have the formspec. I created another block and then used an abm to place the one with the formspec. This seems to work fine.
My question is, is that the best way to do it or is there a better way?
kaadmy wrote:Don wrote:I have another issue though. I have a mts schematic that contains a node with a formspec. When the schematic is placed the node does not have the formspec. I created another block and then used an abm to place the one with the formspec. This seems to work fine.
My question is, is that the best way to do it or is there a better way?
That's how I do it, I couldn't find a better solution.
local on_construct = minetest.registered_nodes[name].on_construct
if on_construct then
on_construct(pos)
end
local SIZE = 200;
minetest.register_node("limit:limit_node", {
diggable = false,
sunlight_propagates = true,
drawtype = "airlike",
})
minetest.register_on_generated(function(minp, maxp, seed)
local c_limit = minetest.get_content_id("limit:limit_node")
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
local data = vm:get_data(minp, maxp)
for i in area:iterp(minp, maxp) do
local currPos = area:position(i)
if math.abs(currPos["x"]) > SIZE/2 or
math.abs(currPos["y"]) > SIZE/2 or
math.abs(currPos["z"]) > SIZE/2 then
data[i] = c_limit;
end
end
vm:set_data(data)
vm:write_to_map(data)
end)
rubenwardy wrote:This is, afaik, due to overgeneration, which causes the c++ mapgen to override your blocks. Paramat is the one to talk to about this.
local data = vm:get_data(emin, emax)
for i in area:iterp(emin, emax) do
paramat wrote:Hybrid Dog yes probably.
All core mapgens work on the 80^3 node mapchunk plus a 16 node deep shell that extends into / overlaps neighbouring mapchunks. Dungeons, large caves and mgv6 dirt/grass all 'overgenerate' into the shell sometimes.
In your code emin emax are the shell limits, minp maxp are the mapchunk limits try:Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
- Code: Select all
local data = vm:get_data(emin, emax)
for i in area:iterp(emin, emax) do
It might help.
Hybrid Dog wrote:as far as l know the client needs to load the chunk, not the server
there's a function to forceload a chunk: [url]dev.minetest.net/minetest.forceload_block[/url]
Sane wrote:Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
- Code: Select all
--[[
Node placer - Places a node on the surface, at a random position in the mg block that contains a grid point defined by cell_size
published under Creative Commons CC0 license.
--]]
-- cell_size must be bigger then mg block size (80) to work.
local cell_size = 150
local item_id = minetest.get_content_id("default:steelblock")
minetest.register_on_generated(function(minp, maxp, seed)
-- If the next_hotspot is not within this mg block then exit
local next_hotspot = {
x = math.ceil(minp.x / cell_size) * cell_size,
y = math.ceil(minp.y / cell_size) * cell_size,
z = math.ceil(minp.z / cell_size) * cell_size
}
if next_hotspot.x > maxp.x or
next_hotspot.y > maxp.y or
next_hotspot.z > maxp.z then return end
-- Place the object somewhere in this block
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local va = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
local vd = vm:get_data()
local r = PcgRandom(seed) -- this ensures that you get the same results each time you generate the world anew.
local item_pos = {
x = r:next(minp.x, maxp.x),
y = r:next(minp.y, maxp.y),
z = r:next(minp.z, maxp.z),
}
-- This is to optimize, because getting the height map is expensive
if minp.y > -200 and maxp.y < 200 then
local hm = minetest.get_mapgen_object("heightmap")
local hz = (item_pos.z - minp.z) * 80
local hx = (item_pos.x - minp.x) % 80
local height = hm[1 + hx + hz]
item_pos.y = height + 1
end
vd[va:indexp(item_pos)] = item_id
--
vm:set_data(vd)
--vm:calc_lighting()
--vm:update_liquids()
vm:write_to_map()
--vm:update_map()
--
end)
GunshipPenguin wrote:This code does work, but I find that certian nodes are not replaced by limit:limit_node like I want them to be.
Ferk wrote:I haven't tested your code, but since you are calculating next_hotspot in all 3 dimensions, wouldn't a new block be created in the same area in the surface when a chunk gets generated further down close to the hotspot below?
Ferk wrote:I know you have checks to avoid placing it in the surface if it's below -200 and above 200 ...
Ferk wrote:Also, if it's below -200 or above 200, it would place the node in a random location, even if it's in the sky or underground, no?
Sane wrote:The hotspot is a single coordinate so it can only be in one mapgen block.
Sane wrote:No, the purpose of of the checks is to avoid getting the hightmap unnecessarily. Just a performance thing.
Ferk wrote:Sane wrote:The hotspot is a single coordinate so it can only be in one mapgen block.
Yes, but after each hotspot is found, a node is placed at the surface (using the heightmap) whenever the chunk that is getting generated is between -200 and 200 (the node in the surface might not be part of the chunk generated).
If this is the case then it's possible for 2 nodes to be placed at heightmap level next to each other, even though the goal was to have them separated by 150 nodes. The hotspots might be separated by that much, but not the nodes you are placing.
Don wrote:I just tested it and it does place 2 nodes close together. I found 3 within a 50 node radius.
Don wrote:The question is how to fix this. I need the nodes to be seperated. If they are close then it will cause an issue with what they do.
Don wrote:Thanks for all your help on this!
Sane wrote:The code is a reply to Don, who wanted to place a node at a 1000 nodes spacing. The intend of the source is to give an general impression on how to go about to solve a thing like that. It is not thought to be the solution.
if (minp.y > dungeon_rooms.origin.y) then
-- avoid the calculation when too high up
if (minp.y > 200) then return end
local cell_size = {
x = dungeon_rooms.stairs_distance * dungeon_rooms.room_area.x,
z = dungeon_rooms.stairs_distance * dungeon_rooms.room_area.z,
}
local next_entrance = {
x = maxp.x - (maxp.x % cell_size.x),
z = maxp.z - (maxp.z % cell_size.z),
}
if (minp.x < next_entrance.x) and (minp.z < next_entrance.z) then
-- Put the entrance spawner on ground level
local hm = minetest.get_mapgen_object("heightmap")
local hz = (next_entrance.z - minp.z) * 80
local hx = (next_entrance.x - minp.x) % 80
next_entrance.y = hm[1 + hx + hz]
-- But only if it's in the generating chunk
if (next_entrance.y < maxp.y) and (next_entrance.y > minp.y) then
minetest.set_node(next_entrance, minetest.get_content_id("dungeon_rooms:entrance_spawner"))
end
end
else
[......]
end
Don wrote:I have been looking for around a half hour and can not find one.
minetest.log("action","Placing node at " .. item_pos.x .. ",".. item_pos.y .. ",".. item_pos.z)
Users browsing this forum: No registered users and 5 guests