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_shadow_caster = true
multi_map.override_bedrock_generator = nil
multi_map.override_skyrock_generator = nil
-- Table with layer specific configuration
multi_map.layers = {}
-- Table with generator chains
multi_map.generators = {}
-- When no suitable generator is found, this generator is used as a fallback
multi_map.fallback_generator = nil
multi_map.layer_names = {}
-- Set the current layer which the mapgen is generating
-- y = absolute y value to be translated to layer
@ -63,8 +61,8 @@ end
-- y = absolute y value to be translated to layer
function multi_map.get_layer_name_y(y)
local l = multi_map.get_layer(y)
if l then
return multi_map.layer_names[l]
if l and multi_map.layers[l] and multi_map.layers[l].name then
return multi_map.layers[l].name
else
return tostring(l)
end
@ -263,6 +261,10 @@ function multi_map.register_fallback_generator(...)
multi_map.fallback_generator = { name = name, generator = generator, arguments = arguments }
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
-- position = the optional layer for which call this generator
-- generator = the function to call
@ -308,18 +310,11 @@ function multi_map.register_generator(...)
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
-- layer = the layer number
function multi_map.get_layer_name(layer)
if multi_map.layer_names[layer] then
return multi_map.layer_names[layer]
if multi_map.layers[layer] and multi_map.layers[layer].name then
return multi_map.layers[layer].name
elseif multi_map.fallback_generator then
return multi_map.fallback_generator.name
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_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
then
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local vm_data = vm:get_data()
if multi_map.override_bedrock_generator then
multi_map.override_bedrock_generator(multi_map.current_layer, vm, area, vm_data, minp, maxp, offset_minp, offset_maxp)
if multi_map.layers[multi_map.current_layer] and
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
multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.node[multi_map.bedrock])
end
vm:set_data(vm_data)
vm:calc_lighting(false)
vm:write_to_map(false)
end
elseif multi_map.generate_skyrock
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
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 vm_data = vm:get_data()
if multi_map.override_skyrock_generator then
multi_map.override_skyrock_generator(multi_map.current_layer, vm, area, vm_data, minp, maxp, offset_minp, offset_maxp)
if multi_map.layers[multi_map.current_layer] and
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
multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.node[multi_map.skyrock])
end
vm:set_lighting({day=15, night=0})
vm:set_data(vm_data)
vm:calc_lighting(false)
vm:write_to_map(false)
end
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 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 remove_shadow_caster = false
-- Add a temporary stone layer above the chunk to ensure caves are dark
if multi_map.generate_shadow_caster and multi_map.get_absolute_centerpoint() >= maxp.y then
-- 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) 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
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"])

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)")
end
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
name = "\""..name.."\","
else

View File

@ -33,8 +33,8 @@ function multi_map.update_hud(player)
local player_name = player:get_player_name()
local layer = multi_map.get_layer(player:get_pos().y)
local offset_y = multi_map.get_offset_y(player:get_pos().y, layer)
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) + 0.5
local hud_text = ""

View File

@ -214,7 +214,7 @@ end
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime;
if timer >= 0.5 then
if timer >= 1 then
for _,player in ipairs(minetest.get_connected_players()) do
local posxz = { x = player:get_pos().x, y = player:get_pos().z }
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.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(19, mmgen_testauri.generate)
multi_map.register_generator(20, mmgen_testauri.generate)

View File

@ -31,7 +31,8 @@ local LUXCHA = 1 / 9 ^ 3
-- 3D noise
local np_terrain = {
multi_map.register_global_3dmap(
"terrain", {
offset = 0,
scale = 1,
spread = {x=384, y=192, z=384},
@ -39,12 +40,13 @@ local np_terrain = {
octaves = 5,
persist = 0.63,
lacunarity = 2.0,
--flags = ""
}
)
-- 2D noise
local np_spike = {
multi_map.register_global_2dmap(
"spike", {
offset = 0,
scale = 1,
spread = {x=128, y=128, z=128},
@ -54,6 +56,7 @@ local np_spike = {
lacunarity = 2.0,
flags = "noeased"
}
)
-- Nodes
@ -86,20 +89,12 @@ minetest.register_node("multi_map_generators:luxore", {
local floatper = math.pi / FLOATPER
-- Set mapgen parameters
-- Generate function
minetest.register_on_mapgen_init(function(mgparams)
minetest.set_mapgen_params({mgname="singlenode", flags="nolight"})
end)
function mmgen_levels.generate(current_layer, vm, area, data, minp, maxp, offset_minp, offset_maxp, params)
-- 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 y1 = maxp.y
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 minpos2d = {x=x0, y=z0}
nobj_terrain = nobj_terrain or minetest.get_perlin_map(np_terrain, chulens3d)
nobj_spike = nobj_spike or minetest.get_perlin_map(np_spike, chulens2d)
local nvals_terrain = nobj_terrain:get3dMap_flat(minpos3d)
local nvals_spike = nobj_spike:get2dMap_flat(minpos2d)
local nvals_terrain = multi_map.get_global_3dmap_flat("terrain", chulens3d, minpos3d)
local nvals_spike = multi_map.get_global_2dmap_flat("spike", chulens2d, minpos2d)
local ni3d = 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_spike = nvals_spike[ni2d]
local spikeoff = 0
if n_spike > TSPIKE then
spikeoff = (n_spike - TSPIKE) ^ 4 * SPIKEAMP
if n_spike > (params.tspike or TSPIKE) then
spikeoff = (n_spike - (params.tspike or TSPIKE)) ^ 4 * (params.spikeamp or SPIKEAMP)
end
local grad = (YSURFCEN - relative_y) / TERSCA + spikeoff
if relative_y > YSURFMAX then
local grad = ((params.ysurfcen or YSURFCEN) - relative_y) / (params.tersca or TERSCA) + spikeoff
if relative_y > (params.ysurfmax or YSURFMAX) then
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
)
elseif relative_y < YSURFMIN then
elseif relative_y < (params.ysurfmin or YSURFMIN) then
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
)
end
local density = n_terrain + grad
if y < y0 then
if density >= TSTONE then
if density >= (params.tstone or TSTONE) then
stable[si] = stable[si] + 1
elseif density <= 0 then
stable[si] = 0
@ -187,8 +179,8 @@ function mmgen_levels.generate(current_layer, vm, area, data, minp, maxp, offset
end
end
elseif y >= y0 and y <= y1 then
if density >= TSTONE then
if math.random() < LUXCHA and relative_y < YSURFMIN
if density >= (params.tstone or TSTONE) then
if math.random() < (params.luxcha or LUXCHA) and relative_y < (params.ysurfmin or YSURFMIN)
and density < 0.01 and data[viu] == c_stone then
data[vi] = c_luxore
else
@ -196,20 +188,20 @@ function mmgen_levels.generate(current_layer, vm, area, data, minp, maxp, offset
end
stable[si] = stable[si] + 1
under[si] = 0
elseif density > 0 and density < TSTONE
and stable[si] >= STABLE and relative_y > YSURFMIN then
if relative_y <= YSAND then
elseif density > 0 and density < (params.tstone or TSTONE)
and stable[si] >= (params.stable or STABLE) and relative_y > (params.ysurfmin or YSURFMIN) then
if relative_y <= (params.ysand or YSAND) then
data[vi] = c_sand
under[si] = 0
else
data[vi] = c_dirt
under[si] = 1
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
stable[si] = 0
under[si] = 0
elseif relative_y <= YLAVA then
elseif relative_y <= (params.ylava or YLAVA) then
data[vi] = c_lava
stable[si] = 0
under[si] = 0
@ -221,7 +213,7 @@ function mmgen_levels.generate(current_layer, vm, area, data, minp, maxp, offset
under[si] = 0
end
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
data[viu] = c_grass
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)
local nodetype = params.nodetype
local height = params.height
local nodetype = "default:stone"
local height = 0
local c_ground
if nodetype then
c_ground = multi_map.node[nodetype]
else
c_ground = multi_map.node["default:stone"]
if params and type(params) == "table" then
if params.nodetype then nodetype = params.nodetype end
if params.height then height = params.height end
end
local c_ground = multi_map.node[nodetype]
if offset_minp.y >= height then
multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.node["air"])
else