[mapgen] GETTING RID OF EMERGE AREAS! Currently for dungeons and villages, and it works

This commit is contained in:
kay27 2021-05-02 03:56:55 +04:00
parent f38c8daab7
commit f4a28cfab0
4 changed files with 54 additions and 68 deletions

View File

@ -37,11 +37,12 @@ minetest_log("action", "[mcl_mapgen] World edges are: mcl_mapgen.EDGE_MIN = " ..
local lvm_block_queue, lvm_chunk_queue, node_block_queue, node_chunk_queue = {}, {}, {}, {} -- Generators' queues
local lvm, block, lvm_block, lvm_chunk, param2, nodes_block, nodes_chunk = 0, 0, 0, 0, 0, 0, 0 -- Requirements: 0 means none; greater than 0 means 'required'
local lvm, block, lvm_block, lvm_chunk, param2, nodes_block, nodes_chunk, safe_functions = 0, 0, 0, 0, 0, 0, 0, 0 -- Requirements: 0 means none; greater than 0 means 'required'
local lvm_buffer, lvm_param2_buffer = {}, {} -- Static buffer pointers
local BS, CS = mcl_mapgen.BS, mcl_mapgen.CS -- Mapblock size (in nodes), Mapchunk size (in blocks)
local LAST_BLOCK, LAST_NODE = CS - 1, BS - 1 -- First mapblock in chunk (node in mapblock) has number 0, last has THIS number. It's for runtime optimization
local offset = mcl_mapgen.OFFSET -- Central mapchunk offset (in blocks)
local CS_NODES = mcl_mapgen.CS_NODES -- 80
local CS_3D = CS * CS * CS
@ -49,6 +50,7 @@ local DEFAULT_PRIORITY = 5000
function mcl_mapgen.register_chunk_generator(callback_function, priority)
nodes_chunk = nodes_chunk + 1
safe_functions = safe_functions + 1
node_chunk_queue[nodes_chunk] = {i = priority or DEFAULT_PRIORITY, f = callback_function}
table.sort(node_chunk_queue, function(a, b) return (a.i <= b.i) end)
end
@ -60,6 +62,7 @@ end
function mcl_mapgen.register_block_generator(callback_function, priority)
block = block + 1
nodes_block = nodes_block + 1
safe_functions = safe_functions + 1
node_block_queue[nodes_block] = {i = priority or DEFAULT_PRIORITY, f = callback_function}
table.sort(node_block_queue, function(a, b) return (a.i <= b.i) end)
end
@ -87,7 +90,7 @@ local current_chunks = {}
minetest.register_on_generated(function(minp, maxp, blockseed)
local minp, maxp, blockseed = minp, maxp, blockseed
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
minetest_log("warning", "[mcl_mapgen] New_chunk=" .. minetest_pos_to_string(minp) .. "..." .. minetest_pos_to_string(maxp) .. ", shall=" .. minetest_pos_to_string(emin) .. "..." .. minetest_pos_to_string(emax) .. ", blockseed=" .. tostring(blockseed))
minetest_log("warning", "[mcl_mapgen] New_chunk=" .. minetest_pos_to_string(minp) .. "..." .. minetest_pos_to_string(maxp) .. ", shell=" .. minetest_pos_to_string(emin) .. "..." .. minetest_pos_to_string(emax) .. ", blockseed=" .. tostring(blockseed))
if lvm > 0 then
vm_context = {lvm_param2_buffer = lvm_param2_buffer, vm = vm, emin = emin, emax = emax, minp = minp, maxp = maxp, blockseed = blockseed}
@ -140,17 +143,15 @@ minetest.register_on_generated(function(minp, maxp, blockseed)
if current_mapgen_block_writes == total_mapgen_block_writes then
-- this block shouldn't be overwritten anymore, no need to keep it in memory
blocks[bx][by][bz] = nil
if not chunks[cx] then chunks[cx] = {} end
if not chunks[cx][cy] then chunks[cx][cy] = {} end
if not chunks[cx][cy][cz] then
if not chunks[cx] then chunks[cx] = {} end
if not chunks[cx][cy] then chunks[cx][cy] = {} end
if not chunks[cx][cy][cz] then chunks[cx][cy][cz] = {counter = 1} end
else
chunks[cx][cy][cz].counter = chunks[cx][cy][cz].counter + 1
if chunks[cx][cy][cz].counter >= CS_3D then
current_chunks[#current_chunks+1] = { x = cx, y = cy, z = cz, s = chunks[cx][cy][cz].seed }
-- this chunk shouldn't be overwritten anymore, no need to keep it in memory
local chunkseed = chunks[cx][cy][cz].seed
process_generated_chunk(cx, cy, cz, chunkseed)
chunks[cx][cy][cz] = nil
if next(chunks[cx][cy]) == nil then chunks[cx][cy] = nil end
if next(chunks[cx]) == nil then chunks[cx] = nil end
@ -196,15 +197,23 @@ minetest.register_on_generated(function(minp, maxp, blockseed)
vm:update_liquids()
end
for _, v in pairs(node_chunk_queue) do
v.f(minp, maxp, blockseed)
for i, b in pairs(current_chunks) do
local cx, cy, cz, seed = b.x, b.y, b.z, b.s
local bx, by, bz = cx * CS + offset, cy * CS + offset, cz * CS + offset
local x, y, z = bx * BS, by * BS, bz * BS
local minp = {x = x, y = y, z = z}
local maxp = {x = x + CS_NODES - 1, y = y + CS_NODES - 1, z = z + CS_NODES - 1}
for _, v in pairs(node_chunk_queue) do
v.f(minp, maxp, seed)
end
current_chunks[i] = nil
end
for i, b in pairs(current_blocks) do
for _, v in pairs(node_block_queue) do
v.f(b.minp, b.maxp, b.seed)
end
current_blocks[id] = nil
current_blocks[i] = nil
end
end)

View File

@ -14,7 +14,7 @@ local swap_node = minetest.swap_node
local set_node = minetest.set_node
local dir_to_facedir = minetest.dir_to_facedir
local get_meta = minetest.get_meta
local emerge_area = minetest.emerge_area
-- local emerge_area = minetest.emerge_area
--vector
local vector_add = vector.add
@ -61,12 +61,14 @@ local surround_vectors = {
{ x=0, y=0, z=1 },
}
local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
if calls_remaining >= 1 then return end
--local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
-- if calls_remaining >= 1 then return end
-- local p1, _, dim, pr = param.p1, param.p2, param.dim, param.pr
-- local check = not (param.dontcheck or false)
local function spawn_dungeon(p1, p2, dim, pr, dontcheck)
local p1, _, dim, pr = param.p1, param.p2, param.dim, param.pr
local x, y, z = p1.x, p1.y, p1.z
local check = not (param.dontcheck or false)
local check = not (dontcheck or false)
-- Check floor and ceiling: Must be *completely* solid
local y_floor = y
@ -401,8 +403,9 @@ local function dungeons_nodes(minp, maxp, blockseed)
local z = pr:next(minp.z, maxp.z-dim.z-1)
local p1 = {x=x,y=y,z=z}
local p2 = {x = x+dim.x+1, y = y+dim.y+1, z = z+dim.z+1}
minetest.log("verbose","[mcl_dungeons] size=" ..minetest.pos_to_string(dim) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))
emerge_area(p1, p2, ecb_spawn_dungeon, {p1=p1, p2=p2, dim=dim, pr=pr})
-- minetest.log("verbose","[mcl_dungeons] size=" ..minetest.pos_to_string(dim) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))
-- emerge_area(p1, p2, ecb_spawn_dungeon, {p1=p1, p2=p2, dim=dim, pr=pr})
spawn_dungeon(p1, p2, dim, pr)
end
end
@ -410,8 +413,9 @@ function mcl_dungeons.spawn_dungeon(p1, _, pr)
if not p1 or not pr or not p1.x or not p1.y or not p1.z then return end
local dim = dungeonsizes[pr:next(1, #dungeonsizes)]
local p2 = {x = p1.x+dim.x+1, y = p1.y+dim.y+1, z = p1.z+dim.z+1}
minetest.log("verbose","[mcl_dungeons] size=" ..minetest.pos_to_string(dim) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))
emerge_area(p1, p2, ecb_spawn_dungeon, {p1=p1, p2=p2, dim=dim, pr=pr, dontcheck=true})
-- minetest.log("verbose","[mcl_dungeons] size=" ..minetest.pos_to_string(dim) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))
-- emerge_area(p1, p2, ecb_spawn_dungeon, {p1=p1, p2=p2, dim=dim, pr=pr, dontcheck=true})
spawn_dungeon(p1, p2, dim, pr, true)
end
mcl_mapgen.register_chunk_generator(dungeons_nodes, 999999)

View File

@ -1,6 +1,8 @@
settlements = {}
settlements.modpath = minetest.get_modpath("mcl_villages")
local minetest_get_spawn_level = minetest.get_spawn_level
dofile(settlements.modpath.."/const.lua")
dofile(settlements.modpath.."/utils.lua")
dofile(settlements.modpath.."/foundation.lua")
@ -53,6 +55,7 @@ end
-- on map generation, try to build a settlement
--
local function build_a_settlement(minp, maxp, blockseed)
minetest.log("action","[mcl_villages] Building village at mapchunk " .. minetest.pos_to_string(minp) .. "..." .. minetest.pos_to_string(maxp) .. ", blockseed = " .. tostring(blockseed))
local pr = PseudoRandom(blockseed)
-- fill settlement_info with buildings and their data
@ -69,28 +72,36 @@ local function build_a_settlement(minp, maxp, blockseed)
settlements.place_schematics(settlement_info, pr)
end
local function ecb_village(blockpos, action, calls_remaining, param)
if calls_remaining >= 1 then return end
local minp, maxp, blockseed = param.minp, param.maxp, param.blockseed
build_a_settlement(minp, maxp, blockseed)
end
-- Disable natural generation in singlenode.
local mg_name = minetest.get_mapgen_setting("mg_name")
if mg_name ~= "singlenode" then
mcl_mapgen.register_chunk_generator(function(minp, maxp, blockseed)
-- local str1 = (maxp.y >= 0 and blockseed % 77 == 17) and "YES" or "no"
-- minetest.log("action","[mcl_villages] " .. str1 .. ": minp=" .. minetest.pos_to_string(minp) .. ", maxp=" .. minetest.pos_to_string(maxp) .. ", blockseed=" .. tostring(blockseed))
-- don't build settlement underground
if maxp.y < 0 then return end
-- randomly try to build settlements
if blockseed % 77 ~= 17 then return end
-- needed for manual and automated settlement building
-- don't build settlements on (too) uneven terrain
--local heightmap = minetest.get_mapgen_object("heightmap")
local height_difference = settlements.evaluate_heightmap()
-- lame and quick replacement of `heightmap` by kay27 - we maybe need to restore `heightmap` analysis if there will be a way for the engine to avoid cavegen conflicts:
--------------------------------------------------------------------------
local height_difference, min, max
local pr1=PseudoRandom(blockseed)
for i=1,pr1:next(5,10) do
local x = pr1:next(0, 40) + minp.x + 19
local z = pr1:next(0, 40) + minp.z + 19
local y = minetest_get_spawn_level(x, z)
if y < (min or y+1) then min = y end
if y > (max or y-1) then max = y end
end
height_difference = max - min + 1
--------------------------------------------------------------------------
if height_difference > max_height_difference then return end
local param={minp=vector.new(minp), maxp=vector.new(maxp), blockseed=blockseed}
minetest.emerge_area(minp, maxp, ecb_village, param)
build_a_settlement(minp, maxp, blockseed)
end)
end
-- manually place villages

View File

@ -207,44 +207,6 @@ function shuffle(tbl, pr)
return table
end
-------------------------------------------------------------------------------
-- evaluate heightmap
-------------------------------------------------------------------------------
function settlements.evaluate_heightmap()
local heightmap = minetest.get_mapgen_object("heightmap")
-- max height and min height, initialize with impossible values for easier first time setting
local max_y = -50000
local min_y = 50000
-- only evaluate the center square of heightmap 40 x 40
local square_start = 1621
local square_end = 1661
for j = 1 , 40, 1 do
for i = square_start, square_end, 1 do
-- skip buggy heightmaps, return high value
if heightmap[i] == -31000 or heightmap[i] == 31000 then
return max_height_difference + 1
end
if heightmap[i] < min_y then
min_y = heightmap[i]
end
if heightmap[i] > max_y then
max_y = heightmap[i]
end
end
-- set next line
square_start = square_start + 80
square_end = square_end + 80
end
-- return the difference between highest and lowest pos in chunk
local height_diff = max_y - min_y
-- filter buggy heightmaps
if height_diff <= 1 then
return max_height_difference + 1
end
-- debug info
settlements.debug("heightdiff ".. height_diff)
return height_diff
end
-------------------------------------------------------------------------------
-- Set array to list
-- https://stackoverflow.com/questions/656199/search-for-an-item-in-a-lua-list
-------------------------------------------------------------------------------