[mcl_mapgen_core] Redesign, mostly to remove water from End and restore static lvm_buffer to speed it up

This commit is contained in:
kay27 2021-03-28 22:56:51 +04:00
parent d07cf64d11
commit cb2aae5a55
8 changed files with 127 additions and 158 deletions

View File

@ -175,3 +175,86 @@ minetest.craftitemdef_default.stack_max = 64
-- Set random seed for all other mods (Remember to make sure no other mod calls this function)
math.randomseed(os.time())
local chunks = {} -- intervals of chunks generated
function mcl_vars.add_chunk(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
local prev
for i, d in pairs(chunks) do
if n <= d[2] then -- we've found it
if (n == d[2]) or (n >= d[1]) then return end -- already here
if n == d[1]-1 then -- right before:
if prev and (prev[2] == n-1) then
prev[2] = d[2]
table.remove(chunks, i)
return
end
d[1] = n
return
end
if prev and (prev[2] == n-1) then --join to previous
prev[2] = n
return
end
table.insert(chunks, i, {n, n}) -- insert new interval before i
return
end
prev = d
end
chunks[#chunks+1] = {n, n}
end
function mcl_vars.is_generated(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
for i, d in pairs(chunks) do
if n <= d[2] then
return (n >= d[1])
end
end
return false
end
-- "Trivial" (actually NOT) function to just read the node and some stuff to not just return "ignore", like mt 5.4 does.
-- p: Position, if it's wrong, {name="error"} node will return.
-- force: optional (default: false) - Do the maximum to still read the node within us_timeout.
-- us_timeout: optional (default: 244 = 0.000244 s = 1/80/80/80), set it at least to 3000000 to let mapgen to finish its job.
--
-- returns node definition, eg. {name="air"}. Unfortunately still can return {name="ignore"}.
function mcl_vars.get_node(p, force, us_timeout)
-- check initial circumstances
if not p or not p.x or not p.y or not p.z then return {name="error"} end
-- try common way
local node = minetest.get_node(p)
if node.name ~= "ignore" then
return node
end
-- copy table to get sure it won't changed by other threads
local pos = {x=p.x,y=p.y,z=p.z}
-- try LVM
minetest.get_voxel_manip():read_from_map(pos, pos)
node = minetest.get_node(pos)
if node.name ~= "ignore" or not force then
return node
end
-- all ways failed - need to emerge (or forceload if generated)
local us_timeout = us_timeout or 244
if mcl_vars.is_generated(pos) then
minetest.chat_send_all("IMPOSSIBLE! Please report this to MCL2 issue tracker!")
minetest.forceload_block(pos)
else
minetest.emerge_area(pos, pos)
end
local t = minetest.get_us_time()
node = minetest.get_node(pos)
while (not node or node.name == "ignore") and (minetest.get_us_time() - t < us_timeout) do
node = minetest.get_node(pos)
end
return node
-- it still can return "ignore", LOL, even if force = true, but only after time out
end

View File

@ -66,12 +66,7 @@ minetest.register_on_shutdown(function()
storage:set_string("nether_exits_keys", minetest.serialize(keys))
end)
mcl_portals.get_node = function(pos)
if mcl_mapgen_core and mcl_mapgen_core.get_node then
mcl_portals.get_node = mcl_mapgen_core.get_node
end
return minetest.get_node(pos)
end
local get_node = mcl_vars.get_node
local set_node = minetest.set_node
local registered_nodes = minetest.registered_nodes
local is_protected = minetest.is_protected
@ -97,7 +92,6 @@ local limits = {
-- Incoming verification performed: two nodes must be portal nodes, and an obsidian below them.
-- If the verification passes - position adds to the table and saves to mod storage on exit.
local function add_exit(p)
local get_node = mcl_portals.get_node
if not p or not p.y or not p.z or not p.x then return end
local x, y, z = floor(p.x), floor(p.y), floor(p.z)
local p = {x = x, y = y, z = z}
@ -202,7 +196,6 @@ local function destroy_nether_portal(pos, node)
local nn, orientation = node.name, node.param2
local obsidian = nn == OBSIDIAN
local get_node = mcl_portals.get_node
local check_remove = function(pos, orientation)
local node = get_node(pos)
if node and (node.name == PORTAL and (orientation == nil or (node.param2 == orientation))) then
@ -315,8 +308,6 @@ function build_nether_portal(pos, width, height, orientation, name)
light_frame(pos.x, pos.y, pos.z, pos.x + (1 - orientation) * (width - 1), pos.y + height - 1, pos.z + orientation * (width - 1))
local get_node = mcl_portals.get_node
-- Build obsidian platform:
for x = pos.x - orientation, pos.x + orientation + (width - 1) * (1 - orientation), 1 + orientation do
for z = pos.z - 1 + orientation, pos.z + 1 - orientation + (width - 1) * orientation, 2 - orientation do
@ -379,7 +370,7 @@ local function finalize_teleport(obj, exit)
-- If player stands, player is at ca. something+0.5 which might cause precision problems, so we used ceil for objpos.y
objpos = {x = floor(objpos.x+0.5), y = ceil(objpos.y), z = floor(objpos.z+0.5)}
if mcl_portals.get_node(objpos).name ~= PORTAL then return end
if get_node(objpos).name ~= PORTAL then return end
-- THIS IS A TEMPORATY CODE SECTION FOR COMPATIBILITY REASONS -- 1 of 2 -- TODO: Remove --
-- Old worlds have no exits indexed - adding the exit to return here:
@ -529,7 +520,7 @@ local function create_portal(pos, limit1, limit2, name, obj)
end
local function available_for_nether_portal(p)
local nn = mcl_portals.get_node(p).name
local nn = get_node(p).name
local obsidian = nn == OBSIDIAN
if nn ~= "air" and minetest.get_item_group(nn, "fire") ~= 1 then
return false, obsidian
@ -636,7 +627,7 @@ local function teleport_no_delay(obj, pos)
-- If player stands, player is at ca. something+0.5 which might cause precision problems, so we used ceil for objpos.y
objpos = {x = floor(objpos.x+0.5), y = ceil(objpos.y), z = floor(objpos.z+0.5)}
if mcl_portals.get_node(objpos).name ~= PORTAL then return end
if get_node(objpos).name ~= PORTAL then return end
local target, dim = get_target(objpos)
if not target then return end

View File

@ -12,6 +12,8 @@ end
local min_y = math.max(mcl_vars.mg_overworld_min, mcl_vars.mg_bedrock_overworld_max) + 1
local max_y = mcl_vars.mg_overworld_max - 1
local get_node = mcl_vars.get_node
-- Calculate the number of dungeon spawn attempts
-- In Minecraft, there 8 dungeon spawn attempts Minecraft chunk (16*256*16 = 65536 blocks).
-- Minetest chunks don't have this size, so scale the number accordingly.
@ -49,8 +51,8 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
local y_floor = y
local y_ceiling = y + dim.y + 1
if check then for tx = x+1, x+dim.x do for tz = z+1, z+dim.z do
if not minetest.registered_nodes[mcl_mapgen_core.get_node({x = tx, y = y_floor , z = tz}).name].walkable
or not minetest.registered_nodes[mcl_mapgen_core.get_node({x = tx, y = y_ceiling, z = tz}).name].walkable then return false end
if not minetest.registered_nodes[get_node({x = tx, y = y_floor , z = tz}).name].walkable
or not minetest.registered_nodes[get_node({x = tx, y = y_ceiling, z = tz}).name].walkable then return false end
end end end
-- Check for air openings (2 stacked air at ground level) in wall positions
@ -63,25 +65,25 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
local x2,z2 = x+dim.x+1, z+dim.z+1
if mcl_mapgen_core.get_node({x=x, y=y+1, z=z}).name == "air" and mcl_mapgen_core.get_node({x=x, y=y+2, z=z}).name == "air" then
if get_node({x=x, y=y+1, z=z}).name == "air" and get_node({x=x, y=y+2, z=z}).name == "air" then
openings_counter = openings_counter + 1
if not openings[x] then openings[x]={} end
openings[x][z] = true
table.insert(corners, {x=x, z=z})
end
if mcl_mapgen_core.get_node({x=x2, y=y+1, z=z}).name == "air" and mcl_mapgen_core.get_node({x=x2, y=y+2, z=z}).name == "air" then
if get_node({x=x2, y=y+1, z=z}).name == "air" and get_node({x=x2, y=y+2, z=z}).name == "air" then
openings_counter = openings_counter + 1
if not openings[x2] then openings[x2]={} end
openings[x2][z] = true
table.insert(corners, {x=x2, z=z})
end
if mcl_mapgen_core.get_node({x=x, y=y+1, z=z2}).name == "air" and mcl_mapgen_core.get_node({x=x, y=y+2, z=z2}).name == "air" then
if get_node({x=x, y=y+1, z=z2}).name == "air" and get_node({x=x, y=y+2, z=z2}).name == "air" then
openings_counter = openings_counter + 1
if not openings[x] then openings[x]={} end
openings[x][z2] = true
table.insert(corners, {x=x, z=z2})
end
if mcl_mapgen_core.get_node({x=x2, y=y+1, z=z2}).name == "air" and mcl_mapgen_core.get_node({x=x2, y=y+2, z=z2}).name == "air" then
if get_node({x=x2, y=y+1, z=z2}).name == "air" and get_node({x=x2, y=y+2, z=z2}).name == "air" then
openings_counter = openings_counter + 1
if not openings[x2] then openings[x2]={} end
openings[x2][z2] = true
@ -89,13 +91,13 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
end
for wx = x+1, x+dim.x do
if mcl_mapgen_core.get_node({x=wx, y=y+1, z=z}).name == "air" and mcl_mapgen_core.get_node({x=wx, y=y+2, z=z}).name == "air" then
if get_node({x=wx, y=y+1, z=z}).name == "air" and get_node({x=wx, y=y+2, z=z}).name == "air" then
openings_counter = openings_counter + 1
if check and openings_counter > 5 then return end
if not openings[wx] then openings[wx]={} end
openings[wx][z] = true
end
if mcl_mapgen_core.get_node({x=wx, y=y+1, z=z2}).name == "air" and mcl_mapgen_core.get_node({x=wx, y=y+2, z=z2}).name == "air" then
if get_node({x=wx, y=y+1, z=z2}).name == "air" and get_node({x=wx, y=y+2, z=z2}).name == "air" then
openings_counter = openings_counter + 1
if check and openings_counter > 5 then return end
if not openings[wx] then openings[wx]={} end
@ -103,13 +105,13 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
end
end
for wz = z+1, z+dim.z do
if mcl_mapgen_core.get_node({x=x, y=y+1, z=wz}).name == "air" and mcl_mapgen_core.get_node({x=x, y=y+2, z=wz}).name == "air" then
if get_node({x=x, y=y+1, z=wz}).name == "air" and get_node({x=x, y=y+2, z=wz}).name == "air" then
openings_counter = openings_counter + 1
if check and openings_counter > 5 then return end
if not openings[x] then openings[x]={} end
openings[x][wz] = true
end
if mcl_mapgen_core.get_node({x=x2, y=y+1, z=wz}).name == "air" and mcl_mapgen_core.get_node({x=x2, y=y+2, z=wz}).name == "air" then
if get_node({x=x2, y=y+1, z=wz}).name == "air" and get_node({x=x2, y=y+2, z=wz}).name == "air" then
openings_counter = openings_counter + 1
if check and openings_counter > 5 then return end
if not openings[x2] then openings[x2]={} end
@ -185,7 +187,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
-- Calculate the mob spawner position, to be re-used for later
local sp = {x = x + math.ceil(dim.x/2), y = y+1, z = z + math.ceil(dim.z/2)}
local rn = minetest.registered_nodes[mcl_mapgen_core.get_node(sp).name]
local rn = minetest.registered_nodes[get_node(sp).name]
if rn and rn.is_ground_content then
table.insert(spawner_posses, sp)
end
@ -200,7 +202,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
-- Do not overwrite nodes with is_ground_content == false (e.g. bedrock)
-- Exceptions: cobblestone and mossy cobblestone so neighborings dungeons nicely connect to each other
local name = mcl_mapgen_core.get_node(p).name
local name = get_node(p).name
if minetest.registered_nodes[name].is_ground_content or name == "mcl_core:cobble" or name == "mcl_core:mossycobble" then
-- Floor
if ty == y then

View File

@ -1,45 +1,8 @@
mcl_mapgen_core = {}
mcl_mapgen_core.registered_generators = {}
local registered_generators = {}
local lvm, nodes, param2 = 0, 0, 0
local generating = {} -- generating chunks
local chunks = {} -- intervals of chunks generated
local function add_chunk(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
local prev
for i, d in pairs(chunks) do
if n <= d[2] then -- we've found it
if (n == d[2]) or (n >= d[1]) then return end -- already here
if n == d[1]-1 then -- right before:
if prev and (prev[2] == n-1) then
prev[2] = d[2]
table.remove(chunks, i)
return
end
d[1] = n
return
end
if prev and (prev[2] == n-1) then --join to previous
prev[2] = n
return
end
table.insert(chunks, i, {n, n}) -- insert new interval before i
return
end
prev = d
end
chunks[#chunks+1] = {n, n}
end
function mcl_mapgen_core.is_generated(pos)
local n = mcl_vars.get_chunk_number(pos) -- unsigned int
for i, d in pairs(chunks) do
if n <= d[2] then
return (n >= d[1])
end
end
return false
end
local lvm_buffer = {}
--
-- Aliases for map generator outputs
@ -1850,24 +1813,22 @@ end
minetest.register_on_generated(function(minp, maxp, blockseed)
minetest.log("action", "[mcl_mapgen_core] Generating chunk " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp))
add_chunk(minp)
local p1, p2 = {x=minp.x, y=minp.y, z=minp.z}, {x=maxp.x, y=maxp.y, z=maxp.z}
if lvm > 0 then
local lvm_used, shadow = false, false
local lb = {} -- buffer
local lb2 = {} -- param2
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local e1, e2 = {x=emin.x, y=emin.y, z=emin.z}, {x=emax.x, y=emax.y, z=emax.z}
local data2
local data = vm:get_data(lb)
local data = vm:get_data(lvm_buffer)
if param2 > 0 then
data2 = vm:get_param2_data(lb2)
end
local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2})
for _, rec in pairs(mcl_mapgen_core.registered_generators) do
for _, rec in pairs(registered_generators) do
if rec.vf then
local lvm_used0, shadow0 = rec.vf(vm, data, data2, p1, p2, area, p1, p2, blockseed)
local lvm_used0, shadow0 = rec.vf(vm, data, data2, e1, e2, area, p1, p2, blockseed)
if lvm_used0 then
lvm_used = true
end
@ -1890,18 +1851,18 @@ minetest.register_on_generated(function(minp, maxp, blockseed)
end
if nodes > 0 then
for _, rec in pairs(mcl_mapgen_core.registered_generators) do
for _, rec in pairs(registered_generators) do
if rec.nf then
rec.nf(p1, p2, blockseed)
end
end
end
-- add_chunk(minp)
mcl_vars.add_chunk(minp)
end)
minetest.register_on_generated=function(node_function)
mcl_mapgen_core.register_generator("mod_"..tostring(#mcl_mapgen_core.registered_generators+1), nil, node_function)
mcl_mapgen_core.register_generator("mod_"..tostring(#registered_generators+1), nil, node_function)
end
function mcl_mapgen_core.register_generator(id, lvm_function, node_function, priority, needs_param2)
@ -1920,18 +1881,18 @@ function mcl_mapgen_core.register_generator(id, lvm_function, node_function, pri
needs_param2 = needs_param2,
}
mcl_mapgen_core.registered_generators[id] = new_record
registered_generators[id] = new_record
table.sort(
mcl_mapgen_core.registered_generators,
registered_generators,
function(a, b)
return (a.i < b.i) or ((a.i == b.i) and (a.vf ~= nil) and (b.vf == nil))
end)
end
function mcl_mapgen_core.unregister_generator(id)
if not mcl_mapgen_core.registered_generators[id] then return end
local rec = mcl_mapgen_core.registered_generators[id]
mcl_mapgen_core.registered_generators[id] = nil
if not registered_generators[id] then return end
local rec = registered_generators[id]
registered_generators[id] = nil
if rec.vf then lvm = lvm - 1 end
if rev.nf then nodes = nodes - 1 end
if rec.needs_param2 then param2 = param2 - 1 end
@ -2134,9 +2095,9 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
-- Nether block fixes:
-- * Replace water with Nether lava.
-- * Replace stone, sand dirt in v6 so the Nether works in v6.
elseif minp.y <= mcl_vars.mg_nether_max and maxp.y >= mcl_vars.mg_nether_min then
elseif emin.y <= mcl_vars.mg_nether_max and emax.y >= mcl_vars.mg_nether_min then
if mg_name == "v6" then
local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
local nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"})
for n=1, #nodes do
local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z)
if data[p_pos] == c_water then
@ -2151,7 +2112,7 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
end
end
else
minetest.emerge_area(minp, maxp, function(blockpos, action, calls_remaining, param)
minetest.emerge_area(emin, emax, function(blockpos, action, calls_remaining, param)
if calls_remaining > 0 then return end
-- local nodes = minetest.find_nodes_in_area(param.minp, param.maxp, {"mcl_core:water_source"})
local nodes = minetest.find_nodes_in_area(param.minp, param.maxp, {"group:water"})
@ -2160,7 +2121,7 @@ local function basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
for _, n in pairs(nodes) do
sn(n, l)
end
end, {minp=vector.new(minp), maxp=vector.new(maxp)})
end, {minp=vector.new(emin), maxp=vector.new(emax)})
end
-- End block fixes:
@ -2231,48 +2192,3 @@ end
mcl_mapgen_core.register_generator("main", basic, nil, 1, true)
-- "Trivial" (actually NOT) function to just read the node and some stuff to not just return "ignore", like 5.3.0 does.
-- p: Position, if it's wrong, {name="error"} node will return.
-- force: optional (default: false) - Do the maximum to still read the node within us_timeout.
-- us_timeout: optional (default: 244 = 0.000244 s = 1/80/80/80), set it at least to 3000000 to let mapgen to finish its job.
--
-- returns node definition, eg. {name="air"}. Unfortunately still can return {name="ignore"}.
function mcl_mapgen_core.get_node(p, force, us_timeout)
-- check initial circumstances
if not p or not p.x or not p.y or not p.z then return {name="error"} end
-- try common way
local node = minetest.get_node(p)
if node.name ~= "ignore" then
return node
end
-- copy table to get sure it won't changed by other threads
local pos = {x=p.x,y=p.y,z=p.z}
-- try LVM
minetest.get_voxel_manip():read_from_map(pos, pos)
node = minetest.get_node(pos)
if node.name ~= "ignore" or not force then
return node
end
-- all ways failed - need to emerge (or forceload if generated)
local us_timeout = us_timeout or 244
if mcl_mapgen_core.is_generated(pos) then
minetest.forceload_block(pos)
else
minetest.emerge_area(pos, pos)
end
local t = minetest.get_us_time()
node = minetest.get_node(pos)
while (not node or node.name == "ignore") and (minetest.get_us_time() - t < us_timeout) do
node = minetest.get_node(pos)
end
return node
-- it still can return "ignore", LOL, even if force = true, but only after time out
end

View File

@ -272,7 +272,7 @@ local function hut_placement_callback(p1, p2, size, orientation, pr)
if not p1 or not p2 then return end
local legs = minetest.find_nodes_in_area(p1, p2, "mcl_core:tree")
for i = 1, #legs do
while minetest.get_item_group(mcl_mapgen_core.get_node({x=legs[i].x, y=legs[i].y-1, z=legs[i].z}, true, 333333).name, "water") ~= 0 do
while minetest.get_item_group(mcl_vars.get_node({x=legs[i].x, y=legs[i].y-1, z=legs[i].z}, true, 333333).name, "water") ~= 0 do
legs[i].y = legs[i].y - 1
minetest.swap_node(legs[i], {name = "mcl_core:tree", param2 = 2})
end

View File

@ -4,7 +4,7 @@
-------------------------------------------------------------------------------
function settlements.build_schematic(vm, data, va, pos, building, replace_wall, name)
-- get building node material for better integration to surrounding
local platform_material = mcl_mapgen_core.get_node(pos)
local platform_material = mcl_vars.get_node(pos)
if not platform_material or (platform_material.name == "air" or platform_material.name == "ignore") then
return
end

View File

@ -52,7 +52,7 @@ function settlements.terraform(settlement_info, pr)
else
-- write ground
-- local p = {x=pos.x+xi, y=pos.y+yi, z=pos.z+zi}
-- local node = mcl_mapgen_core.get_node(p)
-- local node = mcl_vars.get_node(p)
-- if node and node.name ~= "air" then
-- minetest.swap_node(p,{name="air"})
-- end

View File

@ -1,28 +1,5 @@
local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass")
local c_dirt_with_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow")
--local c_dirt_with_dry_grass = minetest.get_content_id("mcl_core:dirt_with_dry_grass")
local c_podzol = minetest.get_content_id("mcl_core:podzol")
local c_sand = minetest.get_content_id("mcl_core:sand")
local c_desert_sand = minetest.get_content_id("mcl_core:redsand")
--local c_silver_sand = minetest.get_content_id("mcl_core:silver_sand")
--
local c_air = minetest.get_content_id("air")
local c_snow = minetest.get_content_id("mcl_core:snow")
local c_fern_1 = minetest.get_content_id("mcl_flowers:fern")
local c_fern_2 = minetest.get_content_id("mcl_flowers:fern")
local c_fern_3 = minetest.get_content_id("mcl_flowers:fern")
local c_rose = minetest.get_content_id("mcl_flowers:poppy")
local c_viola = minetest.get_content_id("mcl_flowers:blue_orchid")
local c_geranium = minetest.get_content_id("mcl_flowers:allium")
local c_tulip = minetest.get_content_id("mcl_flowers:tulip_orange")
local c_dandelion_y = minetest.get_content_id("mcl_flowers:dandelion")
local c_dandelion_w = minetest.get_content_id("mcl_flowers:oxeye_daisy")
local c_bush_leaves = minetest.get_content_id("mcl_core:leaves")
local c_bush_stem = minetest.get_content_id("mcl_core:tree")
local c_a_bush_leaves = minetest.get_content_id("mcl_core:acacialeaves")
local c_a_bush_stem = minetest.get_content_id("mcl_core:acaciatree")
local c_water_source = minetest.get_content_id("mcl_core:water_source")
local c_water_flowing = minetest.get_content_id("mcl_core:water_flowing")
local get_node = mcl_vars.get_node
-------------------------------------------------------------------------------
-- function to copy tables
-------------------------------------------------------------------------------
@ -53,9 +30,9 @@ function settlements.find_surface(pos, wait)
-- check, in which direction to look for surface
local surface_node
if wait then
surface_node = mcl_mapgen_core.get_node(p6, true, 10000000)
surface_node = get_node(p6, true, 10000000)
else
surface_node = mcl_mapgen_core.get_node(p6)
surface_node = get_node(p6)
end
if surface_node.name=="air" or surface_node.name=="ignore" then
itter = -1
@ -65,7 +42,7 @@ function settlements.find_surface(pos, wait)
-- Check Surface_node and Node above
--
if settlements.surface_mat[surface_node.name] then
local surface_node_plus_1 = mcl_mapgen_core.get_node({ x=p6.x, y=p6.y+1, z=p6.z})
local surface_node_plus_1 = get_node({ x=p6.x, y=p6.y+1, z=p6.z})
if surface_node_plus_1 and surface_node and
(string.find(surface_node_plus_1.name,"air") or
string.find(surface_node_plus_1.name,"snow") or
@ -90,7 +67,7 @@ function settlements.find_surface(pos, wait)
return nil
end
cnt = cnt+1
surface_node = mcl_mapgen_core.get_node(p6)
surface_node = get_node(p6)
end
settlements.debug("find_surface5: cnt_max overflow")
return nil