From f4a28cfab0c686c9b750e0c0f53e287a8d7b667f Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 2 May 2021 03:56:55 +0400 Subject: [PATCH] [mapgen] GETTING RID OF EMERGE AREAS! Currently for dungeons and villages, and it works --- mods/CORE/mcl_mapgen/init.lua | 29 +++++++++++++++-------- mods/MAPGEN/mcl_dungeons/init.lua | 22 ++++++++++------- mods/MAPGEN/mcl_villages/init.lua | 33 +++++++++++++++++--------- mods/MAPGEN/mcl_villages/utils.lua | 38 ------------------------------ 4 files changed, 54 insertions(+), 68 deletions(-) diff --git a/mods/CORE/mcl_mapgen/init.lua b/mods/CORE/mcl_mapgen/init.lua index 8859c0b0a..5be3ac488 100644 --- a/mods/CORE/mcl_mapgen/init.lua +++ b/mods/CORE/mcl_mapgen/init.lua @@ -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) diff --git a/mods/MAPGEN/mcl_dungeons/init.lua b/mods/MAPGEN/mcl_dungeons/init.lua index d2458939e..a24e4dc9d 100644 --- a/mods/MAPGEN/mcl_dungeons/init.lua +++ b/mods/MAPGEN/mcl_dungeons/init.lua @@ -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) diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index f1b1de906..2b7109451 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -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 diff --git a/mods/MAPGEN/mcl_villages/utils.lua b/mods/MAPGEN/mcl_villages/utils.lua index 87473cc80..1d94ead0c 100644 --- a/mods/MAPGEN/mcl_villages/utils.lua +++ b/mods/MAPGEN/mcl_villages/utils.lua @@ -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 -------------------------------------------------------------------------------