[mapgen] GETTING RID OF EMERGE AREAS! Currently for dungeons and villages, and it works
parent
f38c8daab7
commit
f4a28cfab0
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
-------------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue