Fixed missing test on the simple generators params (nil check),

parameterized the levels generator settings so they can now be
passed on generator registration, changed levels local noises to
global noises. Fixed HUD offset issue, where it would show the
wrong zone and relative coordinates off by 1. Added support for
per layer specific settings such as enabling/ disabling bedrock
or skyrock per layer, overriding certain other settings or
behavior, etc.
This commit is contained in:
evrooije 2018-08-03 12:28:11 +02:00
parent f24d4a3a80
commit 423c153e47
7 changed files with 135 additions and 95 deletions

View File

@ -24,14 +24,12 @@ multi_map.generate_bedrock = true
multi_map.generate_skyrock = true multi_map.generate_skyrock = true
multi_map.generate_shadow_caster = true multi_map.generate_shadow_caster = true
multi_map.override_bedrock_generator = nil -- Table with layer specific configuration
multi_map.override_skyrock_generator = nil multi_map.layers = {}
-- Table with generator chains -- Table with generator chains
multi_map.generators = {} multi_map.generators = {}
-- When no suitable generator is found, this generator is used as a fallback -- When no suitable generator is found, this generator is used as a fallback
multi_map.fallback_generator = nil multi_map.fallback_generator = nil
multi_map.layer_names = {}
-- Set the current layer which the mapgen is generating -- Set the current layer which the mapgen is generating
-- y = absolute y value to be translated to layer -- y = absolute y value to be translated to layer
@ -63,8 +61,8 @@ end
-- y = absolute y value to be translated to layer -- y = absolute y value to be translated to layer
function multi_map.get_layer_name_y(y) function multi_map.get_layer_name_y(y)
local l = multi_map.get_layer(y) local l = multi_map.get_layer(y)
if l then if l and multi_map.layers[l] and multi_map.layers[l].name then
return multi_map.layer_names[l] return multi_map.layers[l].name
else else
return tostring(l) return tostring(l)
end end
@ -263,6 +261,10 @@ function multi_map.register_fallback_generator(...)
multi_map.fallback_generator = { name = name, generator = generator, arguments = arguments } multi_map.fallback_generator = { name = name, generator = generator, arguments = arguments }
end end
function multi_map.set_layer_params(layer, layer_params)
multi_map.layers[layer] = layer_params
end
-- Register a generator for all if position is left out or one layer if position is specified -- Register a generator for all if position is left out or one layer if position is specified
-- position = the optional layer for which call this generator -- position = the optional layer for which call this generator
-- generator = the function to call -- generator = the function to call
@ -308,18 +310,11 @@ function multi_map.register_generator(...)
end end
end end
-- Set a nice name for this layer, e.g. to use for display on the HUD
-- layer = the layer number
-- name = the name to give to this layer
function multi_map.set_layer_name(layer, name)
multi_map.layer_names[layer] = name
end
-- Get the layer name, e.g. to use for display on the HUD -- Get the layer name, e.g. to use for display on the HUD
-- layer = the layer number -- layer = the layer number
function multi_map.get_layer_name(layer) function multi_map.get_layer_name(layer)
if multi_map.layer_names[layer] then if multi_map.layers[layer] and multi_map.layers[layer].name then
return multi_map.layer_names[layer] return multi_map.layers[layer].name
elseif multi_map.fallback_generator then elseif multi_map.fallback_generator then
return multi_map.fallback_generator.name return multi_map.fallback_generator.name
end end
@ -404,23 +399,56 @@ minetest.register_on_generated(function(minp, maxp)
local offset_minp = { x = minp.x, y = multi_map.get_offset_y(minp.y), z = minp.z } local offset_minp = { x = minp.x, y = multi_map.get_offset_y(minp.y), z = minp.z }
local offset_maxp = { x = maxp.x, y = multi_map.get_offset_y(maxp.y), z = maxp.z } local offset_maxp = { x = maxp.x, y = multi_map.get_offset_y(maxp.y), z = maxp.z }
if multi_map.generate_bedrock and local generate_bedrock = multi_map.generate_bedrock
local generate_skyrock = multi_map.generate_skyrock
if multi_map.generate_bedrock then
if multi_map.layers[multi_map.current_layer] and
not multi_map.layers[multi_map.current_layer].generate_bedrock
then
generate_bedrock = false
end
else
if multi_map.layers[multi_map.current_layer] and
multi_map.layers[multi_map.current_layer].generate_bedrock
then
generate_bedrock = true
end
end
if multi_map.generate_skyrock then
if multi_map.layers[multi_map.current_layer] and
not multi_map.layers[multi_map.current_layer].generate_skyrock
then
generate_skyrock = false
end
else
if multi_map.layers[multi_map.current_layer] and
multi_map.layers[multi_map.current_layer].generate_skyrock
then
generate_skyrock = true
end
end
if generate_bedrock and
multi_map.map_min + multi_map.layers_start + (multi_map.layer_height * multi_map.current_layer) == minp.y multi_map.map_min + multi_map.layers_start + (multi_map.layer_height * multi_map.current_layer) == minp.y
then then
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local vm_data = vm:get_data() local vm_data = vm:get_data()
if multi_map.override_bedrock_generator then if multi_map.layers[multi_map.current_layer] and
multi_map.override_bedrock_generator(multi_map.current_layer, vm, area, vm_data, minp, maxp, offset_minp, offset_maxp) multi_map.layers[multi_map.current_layer].bedrock_generator
then
multi_map.layers[multi_map.current_layer].bedrock_generator(multi_map.current_layer, vm, area, vm_data, minp, maxp, offset_minp, offset_maxp)
else else
multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.node[multi_map.bedrock]) multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.node[multi_map.bedrock])
vm:set_data(vm_data)
vm:calc_lighting(false)
vm:write_to_map(false)
end end
elseif multi_map.generate_skyrock vm:set_data(vm_data)
vm:calc_lighting(false)
vm:write_to_map(false)
elseif generate_skyrock
and (multi_map.map_min + multi_map.layers_start + (multi_map.layer_height * (multi_map.current_layer + 1)) - 80 == minp.y or and (multi_map.map_min + multi_map.layers_start + (multi_map.layer_height * (multi_map.current_layer + 1)) - 80 == minp.y or
multi_map.map_min + multi_map.layers_start + (multi_map.layer_height * (multi_map.current_layer + 1)) - 160 == minp.y multi_map.map_min + multi_map.layers_start + (multi_map.layer_height * (multi_map.current_layer + 1)) - 160 == minp.y
) )
@ -429,16 +457,18 @@ minetest.register_on_generated(function(minp, maxp)
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local vm_data = vm:get_data() local vm_data = vm:get_data()
if multi_map.override_skyrock_generator then if multi_map.layers[multi_map.current_layer] and
multi_map.override_skyrock_generator(multi_map.current_layer, vm, area, vm_data, minp, maxp, offset_minp, offset_maxp) multi_map.layers[multi_map.current_layer].skyrock_generator
then
multi_map.layers[multi_map.current_layer].skyrock_generator(multi_map.current_layer, vm, area, vm_data, minp, maxp, offset_minp, offset_maxp)
else else
multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.node[multi_map.skyrock]) multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.node[multi_map.skyrock])
vm:set_lighting({day=15, night=0})
vm:set_data(vm_data)
vm:calc_lighting(false)
vm:write_to_map(false)
end end
vm:set_lighting({day=15, night=0})
vm:set_data(vm_data)
vm:calc_lighting(false)
vm:write_to_map(false)
elseif multi_map.wrap_layers and multi_map.in_skip_area({ x = minp.x, y = minp.z }) then elseif multi_map.wrap_layers and multi_map.in_skip_area({ x = minp.x, y = minp.z }) then
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
@ -453,8 +483,10 @@ minetest.register_on_generated(function(minp, maxp)
local vm_data = vm:get_data() local vm_data = vm:get_data()
local remove_shadow_caster = false local remove_shadow_caster = false
-- Add a temporary stone layer above the chunk to ensure caves are dark -- Add a temporary shadow caster layer above the chunk to ensure caves are dark
if multi_map.generate_shadow_caster and multi_map.get_absolute_centerpoint() >= maxp.y then if (multi_map.generate_shadow_caster and multi_map.get_absolute_centerpoint() >= maxp.y) or
(multi_map.layers[multi_map.current_layer] and multi_map.layers[multi_map.current_layer].generate_shadow_caster)
then
if vm_data[area:index(minp.x, maxp.y + 1, minp.z)] == multi_map.node["ignore"] then if vm_data[area:index(minp.x, maxp.y + 1, minp.z)] == multi_map.node["ignore"] then
remove_shadow_caster = true remove_shadow_caster = true
multi_map.generate_singlenode_plane(minp, maxp, area, vm_data, maxp.y + 1, multi_map.node["multi_map_core:shadow_caster"]) multi_map.generate_singlenode_plane(minp, maxp, area, vm_data, maxp.y + 1, multi_map.node["multi_map_core:shadow_caster"])

View File

@ -20,7 +20,11 @@ function multi_map.log_state()
minetest.log("action", "[multi_map] - "..name.." "..debug.getinfo(multi_map.fallback_generator.generator).short_src:match("^.+/(.+)$").." (fallback)") minetest.log("action", "[multi_map] - "..name.." "..debug.getinfo(multi_map.fallback_generator.generator).short_src:match("^.+/(.+)$").." (fallback)")
end end
for k,v in pairs(multi_map.generators) do for k,v in pairs(multi_map.generators) do
local name = multi_map.layer_names[k] local name
if multi_map.layers[k] and multi_map.layers[k].name then
name = multi_map.layers[k].name
end
if name then if name then
name = "\""..name.."\"," name = "\""..name.."\","
else else

View File

@ -33,8 +33,8 @@ function multi_map.update_hud(player)
local player_name = player:get_player_name() local player_name = player:get_player_name()
local layer = multi_map.get_layer(player:get_pos().y) local layer = multi_map.get_layer(player:get_pos().y + 0.5)
local offset_y = multi_map.get_offset_y(player:get_pos().y, layer) local offset_y = multi_map.get_offset_y(player:get_pos().y, layer) + 0.5
local hud_text = "" local hud_text = ""

View File

@ -214,7 +214,7 @@ end
local timer = 0 local timer = 0
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
timer = timer + dtime; timer = timer + dtime;
if timer >= 0.5 then if timer >= 1 then
for _,player in ipairs(minetest.get_connected_players()) do for _,player in ipairs(minetest.get_connected_players()) do
local posxz = { x = player:get_pos().x, y = player:get_pos().z } local posxz = { x = player:get_pos().x, y = player:get_pos().z }
local edge = multi_map.get_which_world_edge(posxz) local edge = multi_map.get_which_world_edge(posxz)

View File

@ -19,6 +19,18 @@ multi_map.layer_height_chunks = 20
multi_map.wrap_layers = true multi_map.wrap_layers = true
multi_map.register_fallback_generator(mmgen_simple.generate) multi_map.register_fallback_generator(mmgen_simple.generate)
multi_map.register_generator(0, mmgen_testauri.generate)
multi_map.register_generator(1, mmgen_testauri.generate)
multi_map.set_layer_params(0,
{ name = "Bottom World 1", generate_bedrock = false, generate_skyrock = false, generate_shadow_caster = true })
multi_map.set_layer_params(1,
{ name = "Bottom World 2", generate_bedrock = false, generate_skyrock = true })
multi_map.register_generator(2, mmgen_levels.generate)
multi_map.register_generator(18, mmgen_testauri.generate) multi_map.register_generator(18, mmgen_testauri.generate)
multi_map.register_generator(19, mmgen_testauri.generate) multi_map.register_generator(19, mmgen_testauri.generate)
multi_map.register_generator(20, mmgen_testauri.generate) multi_map.register_generator(20, mmgen_testauri.generate)

View File

@ -31,29 +31,32 @@ local LUXCHA = 1 / 9 ^ 3
-- 3D noise -- 3D noise
local np_terrain = { multi_map.register_global_3dmap(
offset = 0, "terrain", {
scale = 1, offset = 0,
spread = {x=384, y=192, z=384}, scale = 1,
seed = 5900033, spread = {x=384, y=192, z=384},
octaves = 5, seed = 5900033,
persist = 0.63, octaves = 5,
lacunarity = 2.0, persist = 0.63,
--flags = "" lacunarity = 2.0,
} }
)
-- 2D noise -- 2D noise
local np_spike = { multi_map.register_global_2dmap(
offset = 0, "spike", {
scale = 1, offset = 0,
spread = {x=128, y=128, z=128}, scale = 1,
seed = -188900, spread = {x=128, y=128, z=128},
octaves = 3, seed = -188900,
persist = 0.5, octaves = 3,
lacunarity = 2.0, persist = 0.5,
flags = "noeased" lacunarity = 2.0,
} flags = "noeased"
}
)
-- Nodes -- Nodes
@ -86,20 +89,12 @@ minetest.register_node("multi_map_generators:luxore", {
local floatper = math.pi / FLOATPER local floatper = math.pi / FLOATPER
-- Set mapgen parameters -- Generate function
minetest.register_on_mapgen_init(function(mgparams) function mmgen_levels.generate(current_layer, vm, area, data, minp, maxp, offset_minp, offset_maxp, params)
minetest.set_mapgen_params({mgname="singlenode", flags="nolight"})
end)
-- Initialize noise objects to nil if not params then params = {} end
local nobj_terrain = nil
local nobj_spike = nil
-- On generated function
function mmgen_levels.generate(current_layer, vm, area, data, minp, maxp, offset_minp, offset_maxp)
local x1 = maxp.x local x1 = maxp.x
local y1 = maxp.y local y1 = maxp.y
local z1 = maxp.z local z1 = maxp.z
@ -126,11 +121,8 @@ function mmgen_levels.generate(current_layer, vm, area, data, minp, maxp, offset
local minpos3d = {x=x0, y=y0-16, z=z0} local minpos3d = {x=x0, y=y0-16, z=z0}
local minpos2d = {x=x0, y=z0} local minpos2d = {x=x0, y=z0}
nobj_terrain = nobj_terrain or minetest.get_perlin_map(np_terrain, chulens3d) local nvals_terrain = multi_map.get_global_3dmap_flat("terrain", chulens3d, minpos3d)
nobj_spike = nobj_spike or minetest.get_perlin_map(np_spike, chulens2d) local nvals_spike = multi_map.get_global_2dmap_flat("spike", chulens2d, minpos2d)
local nvals_terrain = nobj_terrain:get3dMap_flat(minpos3d)
local nvals_spike = nobj_spike:get2dMap_flat(minpos2d)
local ni3d = 1 local ni3d = 1
local ni2d = 1 local ni2d = 1
@ -153,25 +145,25 @@ function mmgen_levels.generate(current_layer, vm, area, data, minp, maxp, offset
local n_terrain = nvals_terrain[ni3d] local n_terrain = nvals_terrain[ni3d]
local n_spike = nvals_spike[ni2d] local n_spike = nvals_spike[ni2d]
local spikeoff = 0 local spikeoff = 0
if n_spike > TSPIKE then if n_spike > (params.tspike or TSPIKE) then
spikeoff = (n_spike - TSPIKE) ^ 4 * SPIKEAMP spikeoff = (n_spike - (params.tspike or TSPIKE)) ^ 4 * (params.spikeamp or SPIKEAMP)
end end
local grad = (YSURFCEN - relative_y) / TERSCA + spikeoff local grad = ((params.ysurfcen or YSURFCEN) - relative_y) / (params.tersca or TERSCA) + spikeoff
if relative_y > YSURFMAX then if relative_y > (params.ysurfmax or YSURFMAX) then
grad = math.max( grad = math.max(
-FLOATFAC * math.abs(math.cos((relative_y - YSURFMAX) * floatper)), (-1 * (params.floatfac or FLOATFAC)) * math.abs(math.cos((relative_y - (params.ysurfmax or YSURFMAX)) * floatper)),
grad grad
) )
elseif relative_y < YSURFMIN then elseif relative_y < (params.ysurfmin or YSURFMIN) then
grad = math.min( grad = math.min(
UNDERFAC * (relative_y - YUNDERCEN) ^ 2 + UNDEROFF, (params.underfac or UNDERFAC) * (relative_y - (params.yundercen or YUNDERCEN)) ^ 2 + (params.underoff or UNDEROFF),
grad grad
) )
end end
local density = n_terrain + grad local density = n_terrain + grad
if y < y0 then if y < y0 then
if density >= TSTONE then if density >= (params.tstone or TSTONE) then
stable[si] = stable[si] + 1 stable[si] = stable[si] + 1
elseif density <= 0 then elseif density <= 0 then
stable[si] = 0 stable[si] = 0
@ -187,8 +179,8 @@ function mmgen_levels.generate(current_layer, vm, area, data, minp, maxp, offset
end end
end end
elseif y >= y0 and y <= y1 then elseif y >= y0 and y <= y1 then
if density >= TSTONE then if density >= (params.tstone or TSTONE) then
if math.random() < LUXCHA and relative_y < YSURFMIN if math.random() < (params.luxcha or LUXCHA) and relative_y < (params.ysurfmin or YSURFMIN)
and density < 0.01 and data[viu] == c_stone then and density < 0.01 and data[viu] == c_stone then
data[vi] = c_luxore data[vi] = c_luxore
else else
@ -196,20 +188,20 @@ function mmgen_levels.generate(current_layer, vm, area, data, minp, maxp, offset
end end
stable[si] = stable[si] + 1 stable[si] = stable[si] + 1
under[si] = 0 under[si] = 0
elseif density > 0 and density < TSTONE elseif density > 0 and density < (params.tstone or TSTONE)
and stable[si] >= STABLE and relative_y > YSURFMIN then and stable[si] >= (params.stable or STABLE) and relative_y > (params.ysurfmin or YSURFMIN) then
if relative_y <= YSAND then if relative_y <= (params.ysand or YSAND) then
data[vi] = c_sand data[vi] = c_sand
under[si] = 0 under[si] = 0
else else
data[vi] = c_dirt data[vi] = c_dirt
under[si] = 1 under[si] = 1
end end
elseif relative_y > YSURFMIN and relative_y <= YWATER then elseif relative_y > (params.ysurfmin or YSURFMIN) and relative_y <= (params.ywater or YWATER) then
data[vi] = c_water data[vi] = c_water
stable[si] = 0 stable[si] = 0
under[si] = 0 under[si] = 0
elseif relative_y <= YLAVA then elseif relative_y <= (params.ylava or YLAVA) then
data[vi] = c_lava data[vi] = c_lava
stable[si] = 0 stable[si] = 0
under[si] = 0 under[si] = 0
@ -221,7 +213,7 @@ function mmgen_levels.generate(current_layer, vm, area, data, minp, maxp, offset
under[si] = 0 under[si] = 0
end end
elseif y == y1 + 1 then elseif y == y1 + 1 then
if density <= 0 and relative_y > YWATER then -- air, possibly just above surface if density <= 0 and relative_y > (params.ywater or YWATER) then -- air, possibly just above surface
if under[si] == 1 then if under[si] == 1 then
data[viu] = c_grass data[viu] = c_grass
end end

View File

@ -2,16 +2,16 @@ mmgen_simple = {}
function mmgen_simple.generate(current_layer, vm, area, vm_data, minp, maxp, offset_minp, offset_maxp, params) function mmgen_simple.generate(current_layer, vm, area, vm_data, minp, maxp, offset_minp, offset_maxp, params)
local nodetype = params.nodetype local nodetype = "default:stone"
local height = params.height local height = 0
local c_ground if params and type(params) == "table" then
if nodetype then if params.nodetype then nodetype = params.nodetype end
c_ground = multi_map.node[nodetype] if params.height then height = params.height end
else
c_ground = multi_map.node["default:stone"]
end end
local c_ground = multi_map.node[nodetype]
if offset_minp.y >= height then if offset_minp.y >= height then
multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.node["air"]) multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.node["air"])
else else