forked from MineClone5/MineClone5
[mapgen] Add undebugged `CORE/mcl_mapgen` mod for further integration
This commit is contained in:
parent
3e3f53efbd
commit
49ac211f87
|
@ -0,0 +1,54 @@
|
||||||
|
# mcl_mapgen
|
||||||
|
============
|
||||||
|
This mod helps to avoid problems caused by Minetest's 'chunk-in-shell' feature of mapgen.cpp.
|
||||||
|
It also queues your generators to run them in proper order.
|
||||||
|
|
||||||
|
|
||||||
|
=========================================================================
|
||||||
|
## mcl_mapgen.register_chunk_generator(chunk_callback_function, priority)
|
||||||
|
=========================================================================
|
||||||
|
UNSAFE! See below. Registers callback function to be called when current chunk generation is finished.
|
||||||
|
`callback_function`: chunk callback function definition, see below;
|
||||||
|
`priority`: order number - the less, the earlier.
|
||||||
|
### Chunk callback function definition:
|
||||||
|
`function(minp, maxp, seed)`:
|
||||||
|
`minp` & `maxp`: minimum and maximum chunk position;
|
||||||
|
`seed`: seed of this mapchunk.
|
||||||
|
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
## mcl_mapgen.register_chunk_generator_lvm(callback_function, priority)
|
||||||
|
=======================================================================
|
||||||
|
UNSAFE! See below. Registers callback function to be called when current chunk generation is finished.
|
||||||
|
`vm_context` passes into callback function and should be returned back.
|
||||||
|
`callback_function`: chunk callback LVM function definition, see below;
|
||||||
|
`priority`: order number - the less, the earlier.
|
||||||
|
### Chunk callback LVM function definition:
|
||||||
|
Function MUST RETURN `vm_context`. It passes into next callback function from the queue.
|
||||||
|
`function(vm_context)`:
|
||||||
|
`vm_context` is a table which already contains some LVM data and some of them can be added in callback function:
|
||||||
|
`minp` & `maxp`: minimum and maximum chunk position;
|
||||||
|
`seed`: seed of this mapchunk.
|
||||||
|
|
||||||
|
|
||||||
|
===================================================================
|
||||||
|
## mcl_mapgen.register_block_generator(callback_function, priority)
|
||||||
|
===================================================================
|
||||||
|
Registers callback function to be called when block (usually 16x16x16 nodes) generation is finished.
|
||||||
|
`callback_function`: block callback function definition, see below;
|
||||||
|
`priority`: order number - the less, the earlier.
|
||||||
|
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
## mcl_mapgen.register_block_generator_lvm(callback_function, priority)
|
||||||
|
=======================================================================
|
||||||
|
Registers callback function to be called when block (usually 16x16x16 nodes) generation is finished.
|
||||||
|
`vm_context` passes into callback function and should be returned back.
|
||||||
|
`callback_function`: block callback LVM function definition, see below;
|
||||||
|
`priority`: order number - the less, the earlier.
|
||||||
|
|
||||||
|
|
||||||
|
===============================
|
||||||
|
## mcl_mapgen.get_far_node(pos)
|
||||||
|
===============================
|
||||||
|
Returns node if it is generated. Otherwise returns `{name = "ignore"}`.
|
|
@ -0,0 +1,146 @@
|
||||||
|
mcl_mapgen = {}
|
||||||
|
|
||||||
|
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 -- Requirements: 0 means none; greater than 0 means 'required'
|
||||||
|
local lvm_buffer, lvm_param2_buffer = {}, {} -- Static buffer pointers
|
||||||
|
local BS, CS = mcl_vars.MAP_BLOCKSIZE, mcl_vars.chunksize -- 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 = math.floor(mcl_vars.central_chunk_offset_in_nodes / BS) -- Central mapchunk offset (in blocks)
|
||||||
|
|
||||||
|
local DEFAULT_PRIORITY = 5000
|
||||||
|
|
||||||
|
local minetest_log, math_floor = minetest.log, math.floor
|
||||||
|
|
||||||
|
function mcl_mapgen.register_chunk_generator(callback_function, priority)
|
||||||
|
nodes_chunk = nodes_chunk + 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
|
||||||
|
function mcl_mapgen.register_chunk_generator_lvm(callback_function, priority)
|
||||||
|
lvm = lvm + 1
|
||||||
|
lvm_chunk_queue[lvm_chunk] = {i = priority or DEFAULT_PRIORITY, f = callback_function}
|
||||||
|
table.sort(lvm_chunk_queue, function(a, b) return (a.i <= b.i) end)
|
||||||
|
end
|
||||||
|
function mcl_mapgen.register_block_generator(callback_function, priority)
|
||||||
|
block = block + 1
|
||||||
|
nodes_block = nodes_block + 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
|
||||||
|
function mcl_mapgen.register_block_generator_lvm(callback_function, priority)
|
||||||
|
block = block + 1
|
||||||
|
lvm = lvm + 1
|
||||||
|
lvm_block = lvm_block + 1
|
||||||
|
lvm_block_queue[lvm_block] = {i = priority or DEFAULT_PRIORITY, f = callback_function}
|
||||||
|
table.sort(lvm_block_queue, function(a, b) return (a.i <= b.i) end)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local blocks = minetest.deserialize( storage:get_string("mapgen_blocks") or "return {}") or {}
|
||||||
|
minetest.register_on_shutdown(function() storage:set_string("mapgen_blocks", minetest.serialize(blocks)) end)
|
||||||
|
|
||||||
|
local vm_context-- here will be many references and flags, like: param2, light_data, heightmap, biomemap, heatmap, humiditymap, gennotify, write_lvm, write_param2, shadow
|
||||||
|
local data, data2, area
|
||||||
|
local current_blocks = {}
|
||||||
|
|
||||||
|
minetest.register_on_generated(function(minp, maxp, blockseed)
|
||||||
|
local minp, maxp, blockseed = minp, maxp, blockseed
|
||||||
|
minetest_log("verbose", "[mcl_mapgen] New chunk: minp=" .. minetest.pos_to_string(minp) .. ", maxp=" .. minetest.pos_to_string(maxp) .. ", blockseed=" .. blockseed)
|
||||||
|
|
||||||
|
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
||||||
|
|
||||||
|
if lvm > 0 then
|
||||||
|
vm_context = {lvm_param2_buffer = lvm_param2_buffer, vm = vm, emin = emin, emax = emax, minp = minp, maxp = maxp, blockseed = blockseed}
|
||||||
|
data = vm:get_data(lvm_buffer)
|
||||||
|
vm_context.data = data
|
||||||
|
area = VoxelArea:new({MinEdge=emin, MaxEdge=emax})
|
||||||
|
vm_context.area = area
|
||||||
|
for _, v in pairs(lvm_chunk_queue) do
|
||||||
|
vm_context = v.f(vm_context)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if block > 0 then
|
||||||
|
local x0, y0, z0 = minp.x, minp.y, minp.z
|
||||||
|
local bx0, by0, bz0 = math_floor(x0/BS), math_floor(y0/BS), math_floor(z0/BS)
|
||||||
|
local x1, y1, z1, x2, y2, z2 = emin.x, emin.y, emin.z, emax.x, emax.y, emax.z
|
||||||
|
local x, y, z = x1, y1, z1 -- iterate 7x7x7 mapchunk, {x,y,z} - first node pos. of mapblock
|
||||||
|
local bx, by, bz -- block coords (in blocs)
|
||||||
|
local box, boy, boz -- block offsets in chunks (in blocks)
|
||||||
|
while x < x2 do
|
||||||
|
bx = math_floor(x/BS)
|
||||||
|
local block_pos_offset_removed = bx - offset
|
||||||
|
box = block_pos_offset_removed % CS
|
||||||
|
if not blocks[bx] then blocks[bx]={} end
|
||||||
|
local total_mapgen_block_writes_through_x = (box > 0 and box < LAST_BLOCK) and 4 or 8
|
||||||
|
while y < y2 do
|
||||||
|
by = math_floor(y/BS)
|
||||||
|
block_pos_offset_removed = by - offset
|
||||||
|
boy = block_pos_offset_removed % CS
|
||||||
|
if not blocks[bx][by] then blocks[bx][by]={} end
|
||||||
|
local total_mapgen_block_writes_through_y = (boy > 0 and boy < LAST_BLOCK) and math_floor(total_mapgen_block_writes_through_x / 2) or total_mapgen_block_writes_through_x
|
||||||
|
while z < z2 do
|
||||||
|
bz = math_floor(z/BS)
|
||||||
|
block_pos_offset_removed = bz - offset
|
||||||
|
boz = block_pos_offset_removed % CS
|
||||||
|
local total_mapgen_block_writes = (boz > 0 and boz < LAST_BLOCK) and math_floor(total_mapgen_block_writes_through_y / 2) or total_mapgen_block_writes_through_y
|
||||||
|
local current_mapgen_block_writes = blocks[bx][by][bz] and (blocks[bx][by][bz] + 1) or 1
|
||||||
|
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
|
||||||
|
vm_context.seed = blockseed + box * 7 + boy * 243 + boz * 11931
|
||||||
|
if lvm_block > 0 then
|
||||||
|
vm_context.minp, vm_content.maxp = {x=x, y=y, z=z}, {x=x+LAST_NODE, y=y+LAST_NODE, z=z+LAST_NODE}
|
||||||
|
for _, v in pairs(lvm_block_queue) do
|
||||||
|
vm_context = v.f(vm_context)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if nodes_block > 0 then
|
||||||
|
current_blocks[#current_blocks+1] = { minp = {x=x, y=y, z=z}, maxp = {x=pos.x+LAST_NODE, y=pos.y+LAST_NODE, z=pos.z+LAST_NODE}, seed = seed }
|
||||||
|
end
|
||||||
|
else
|
||||||
|
blocks[bx][by][bz] = current_mapgen_block_writes
|
||||||
|
end
|
||||||
|
z = z + BS
|
||||||
|
end
|
||||||
|
if next(blocks[bx][by]) == nil then blocks[bx][by] = nil end
|
||||||
|
z = z1
|
||||||
|
y = y + BS
|
||||||
|
end
|
||||||
|
if next(blocks[bx]) == nil then blocks[bx] = nil end
|
||||||
|
y = y1
|
||||||
|
x = x + BS
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if vm_context.write then
|
||||||
|
vm:set_data(data)
|
||||||
|
end
|
||||||
|
if vm_context.write_param2 then
|
||||||
|
vm:set_param2_data(data2)
|
||||||
|
end
|
||||||
|
vm:calc_lighting(p1, p2, shadow)
|
||||||
|
vm:write_to_map()
|
||||||
|
vm:update_liquids()
|
||||||
|
|
||||||
|
for _, v in pairs(node_chunk_queue) do
|
||||||
|
v.f(minp, maxp, blockseed)
|
||||||
|
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
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
minetest.register_on_generated = mcl_mapgen.register_chunk_generator
|
||||||
|
|
||||||
|
function mcl_mapgen.get_far_node(p)
|
||||||
|
local p = p
|
||||||
|
local node = minetest_get_node(p)
|
||||||
|
if node.name ~= "ignore" then return node end
|
||||||
|
minetest_get_voxel_manip():read_from_map(p, p)
|
||||||
|
return minetest_get_node(p)
|
||||||
|
end
|
|
@ -0,0 +1,4 @@
|
||||||
|
name = mcl_mapgen
|
||||||
|
author = kay27
|
||||||
|
description = MineClone 2 MapGen Basic Stuff
|
||||||
|
depends = mcl_init
|
Loading…
Reference in New Issue