Created framework for supporting multiple map generators per layer, with

a fallback (or default if need be) generator in case no layer specified
generator is found. Added sample/ basis mod to demonstrate registration
of map generators. Rewrote Proxima Testauri map generator to conform to
multi_map, simple map generator is fallback in demo. Testauri now uses
a single noise which increases generation time but reduces memory usage.
To try and reduce generation time, it keeps track of the last layer used
and based on that will not reinitialize unless the layer changes.
This commit is contained in:
evrooije 2018-07-18 23:22:18 +02:00
parent d6d827849d
commit 35d768d79f
9 changed files with 274 additions and 6 deletions

View File

@ -16,6 +16,7 @@ multi_map.generate_bedrock = true
multi_map.generate_skyrock = true
multi_map.generators = {}
multi_map.fallback_generator = nil
function multi_map.set_current_layer(y)
for l = 0, multi_map.number_of_layers do
@ -32,8 +33,39 @@ function multi_map.get_offset_y(y)
return y - center_point
end
function multi_map.append_generator(generator)
table.insert(multi_map.generators, generator)
function multi_map.register_fallback_generator(generator)
multi_map.fallback_generator = generator
end
function multi_map.register_generator(...)
local arg = {...}
local position
local generator
if arg[2] then
position = arg[1]
generator = arg[2]
else
generator = arg[1]
end
if not position then
for i = 0, multi_map.number_of_layers - 1 do
local t = multi_map.generators[i]
if not t then
t = {}
multi_map.generators[i] = t
end
table.insert(t, generator)
end
else
local t = multi_map.generators[position]
if not t then
t = {}
multi_map.generators[position] = t
end
table.insert(t, generator)
end
end
function multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, content_id)
@ -53,11 +85,10 @@ local firstrun = true
multi_map.c_stone = nil
multi_map.c_air = nil
multi_map.c_water = nil
multi_map.c_lava = nil
multi_map.c_bedrock = nil
multi_map.c_skyrock = nil
minetest.set_mapgen_params({mgname = "singlenode"})
minetest.register_on_mapgen_init(function(mapgen_params)
if multi_map.number_of_layers * multi_map.layer_height > multi_map.map_height then
minetest.log("error", "Number of layers for the given layer height exceeds map height!")
@ -69,6 +100,7 @@ minetest.register_on_generated(function(minp, maxp)
multi_map.c_stone = minetest.get_content_id("default:stone")
multi_map.c_air = minetest.get_content_id("air")
multi_map.c_water = minetest.get_content_id("default:water_source")
multi_map.c_lava = minetest.get_content_id("default:lava_source")
multi_map.c_bedrock = minetest.get_content_id(multi_map.bedrock)
multi_map.c_skyrock = minetest.get_content_id(multi_map.skyrock)
firstrun = false
@ -110,8 +142,18 @@ minetest.register_on_generated(function(minp, maxp)
vm:calc_lighting(false)
vm:write_to_map(false)
else
for i,f in ipairs(multi_map.generators) do
f(multi_map.current_layer, minp, maxp, offset_minp, offset_maxp)
local t = multi_map.generators[multi_map.current_layer]
if not t then
if multi_map.fallback_generator then
multi_map.fallback_generator(multi_map.current_layer, minp, maxp, offset_minp, offset_maxp)
else
minetest.log("error", "Generator for layer "..multi_map.current_layer.." missing and no fallback specified, exiting mapgen!")
return
end
else
for i,f in ipairs(t) do
f(multi_map.current_layer, minp, maxp, offset_minp, offset_maxp)
end
end
end
end)

View File

@ -0,0 +1,11 @@
local multi_map_generators_path = minetest.get_modpath("multi_map_generators")
--dofile(multi_map_generators_path.."/mmgen_levels.lua")
--dofile(multi_map_generators_path.."/mmgen_lvm_example.lua")
dofile(multi_map_generators_path.."/mmgen_simple.lua")
dofile(multi_map_generators_path.."/mmgen_testauri.lua")
multi_map.register_fallback_generator(mmgen_simple.generate)
multi_map.register_generator(11, mmgen_testauri.generate)
multi_map.register_generator(12, mmgen_testauri.generate)
multi_map.register_generator(13, mmgen_testauri.generate)

View File

@ -0,0 +1,16 @@
function generate(current_layer, minp, maxp, offset_minp, offset_maxp)
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local vm_data = vm:get_data()
if offset_minp.y >= 0 then
multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.c_air)
vm:set_lighting({day=15, night=0})
else
multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.c_stone)
end
vm:set_data(vm_data)
vm:calc_lighting(false)
vm:write_to_map(false)
end
multi_map.append_generator(generate)

View File

@ -0,0 +1,16 @@
mmgen_simple = {}
function mmgen_simple.generate(current_layer, minp, maxp, offset_minp, offset_maxp)
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local vm_data = vm:get_data()
if offset_minp.y >= 0 then
multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.c_air)
vm:set_lighting({day=15, night=0})
else
multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.c_stone)
end
vm:set_data(vm_data)
vm:calc_lighting(false)
vm:write_to_map(false)
end

View File

@ -0,0 +1,183 @@
mmgen_testauri = {}
local layers = {}
mmgen_testauri.water_height = 0
mmgen_testauri.seed = 835726
math.randomseed(mmgen_testauri.seed)
for i = 0, multi_map.number_of_layers -1 do
local height_map_seed = math.random(-1000000000000, 1000000000000)
local terrain_type_seed = math.random(-1000000000000, 1000000000000)
local mountain_peak_seed = math.random(-1000000000000, 1000000000000)
layers[i] = {
height_map_params = {
offset = 0,
scale = 50,
spread = {x=2048, y=2048, z=2048},
seed = height_map_seed,
octaves = 7,
persist = 0.7
},
terrain_type_params = {
offset = 2.5,
scale = 2.5,
spread = {x=1024, y=1024, z=1024},
seed = terrain_type_seed,
octaves = 6,
persist = 0.6
},
mountain_peak_params = {
offset = -75,
scale = 125,
spread = {x=256, y=256, z=256},
seed = mountain_peak_seed,
octaves = 7,
persist = 0.6
},
}
end
mmgen_testauri.cave_seed = 6568239
mmgen_testauri.lake_seed = 6568239
local last_layer
-- Base terrain is the lower frequency, lower amplitude noise
-- Terrain type is a multiplier that can dampen terrain to make
-- flat plains, hills or mountains
-- Mountain peak generates peaks when greater than zero, making
-- jagged and rugged peaks on the surface or mountain tops
local height_map
local terrain_type_map
local mountain_peak_map
local lake_map
local height_map_2dmap = {}
local terrain_type_2dmap = {}
local mountain_peak_2dmap = {}
local lake_3dmap = {}
local cave_map
local perlin_worm_start_map
local perlin_worm_yaw_map
local perlin_worm_pitch_map
local cave_3dmap = {}
local perlin_worm_start_3dmap = {}
local perlin_worm_yaw_3dmap = {}
local perlin_worm_pitch_3dmap = {}
local perlin_worms = {}
local lake_params = {
offset = 0,
scale = 125,
spread = {x=256, y=256, z=256},
seed = mmgen_testauri.lake_seed,
octaves = 6,
persist = 0.6
}
local cave_params = {
offset = 0,
scale = 10,
spread = {x=128, y=128, z=128},
seed = mmgen_testauri.cave_seed,
octaves = 5,
persist = 0.8
}
local perlin_worm_start_params = {
offset = 0,
scale = 1,
spread = {x=256, y=256, z=256},
seed = 9876,
octaves = 7,
persist = 0.7
}
function mmgen_testauri.generate(current_layer, minp, maxp, offset_minp, offset_maxp)
local sidelen = maxp.x - minp.x + 1
local blocklen = sidelen / 5
--3d
local chulenxyz = {x = sidelen, y = sidelen, z = sidelen}
--2d
local chulenxz = {x = sidelen, y = sidelen, z = 1}
local minposxyz = {x = minp.x, y = minp.y - 1, z = minp.z}
local minposxz = {x = minp.x, y = minp.z}
-- strides for voxelmanip
local ystridevm = sidelen + 32
local zstridevm = ystridevm ^ 2
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local vm_data = vm:get_data()
if last_layer ~= current_layer then
height_map = minetest.get_perlin_map(layers[current_layer].height_map_params, chulenxz)
terrain_type_map = minetest.get_perlin_map(layers[current_layer].terrain_type_params, chulenxz)
mountain_peak_map = minetest.get_perlin_map(layers[current_layer].mountain_peak_params, chulenxz)
end
cave_map = cave_map or minetest.get_perlin_map(cave_params, chulenxyz)
-- perlin_worm_start_map = perlin_worm_start_map or minetest.get_perlin_map(perlin_worm_start_params, chulenxyz)
height_map:get2dMap_flat(minposxz, height_map_2dmap)
terrain_type_map:get2dMap_flat(minposxz, terrain_type_2dmap)
mountain_peak_map:get2dMap_flat(minposxz, mountain_peak_2dmap)
cave_map:get3dMap_flat(minposxyz, cave_3dmap)
-- perlin_worm_start_map:get3dMap_flat(minposxyz, perlin_worm_start_3dmap)
-- 3D perlinmap indexes
local nixyz = 1
-- 2D perlinmap indexes
local nixz = 1
-- local worm_started = false
for z = minp.z, maxp.z do
local niz
local oy = offset_minp.y
for y = minp.y, maxp.y do
local vi = area:index(minp.x, y, z)
for x = minp.x, maxp.x do
local nix
local terrain_type = terrain_type_2dmap[nixz]
local height = terrain_type * height_map_2dmap[nixz]
if mountain_peak_2dmap[nixz] > 0 then
height = height + mountain_peak_2dmap[nixz]
end
if oy <= height then
vm_data[vi] = multi_map.c_stone
elseif oy <= mmgen_testauri.water_height then
vm_data[vi] = multi_map.c_water
end
-- Increment noise index.
nixyz = nixyz + 1
nixz = nixz + 1
-- Increment voxelmanip index along x row.
-- The voxelmanip index increases by 1 when
-- moving by 1 node in the +x direction.
vi = vi + 1
end
nixz = nixz - sidelen
oy = oy + 1
end
nixz = nixz + sidelen
end
vm:set_data(vm_data)
vm:update_liquids()
vm:calc_lighting()
vm:write_to_map()
end