diff --git a/multi_map_core/core.lua b/multi_map_core/core.lua index 57c9889..f141bdc 100644 --- a/multi_map_core/core.lua +++ b/multi_map_core/core.lua @@ -2,6 +2,7 @@ multi_map.number_of_layers = 24 -- How may layers to generate multi_map.layers_start_chunk = 0 -- Y level where to start generating layers, in chunks multi_map.layer_height_chunks = 32 -- Height of each layer, in chunks +multi_map.wrap_layers = false -- Either MT engine defaults or derived from above values, to be used for more readable calculations multi_map.layer_height = nil @@ -17,9 +18,14 @@ multi_map.map_max = 30927 multi_map.bedrock = "multi_map_core:bedrock" -- Node to use to fill the bottom of a layer multi_map.skyrock = "multi_map_core:skyrock" -- Node to use to fill the top of a layer --- Whether to generate a bedrock layer under a layer/ skyrock above a layer +-- Whether to generate a bedrock layer under a layer/ skyrock above a layer/ shadow caster +-- above undeground mapchunks 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 generator chains multi_map.generators = {} @@ -148,7 +154,9 @@ function multi_map.register_global_2dmap(name, params) spread = {x=params.spread.x, y=params.spread.y, z=params.spread.z}, seed = math.random(-1000000000000, 1000000000000), octaves = params.octaves, - persist = params.persist + persist = params.persist, + lacunarity = params.lacunarity, + flags = params.flags, } multi_map.global_2d_params[name][i] = new_params end @@ -159,23 +167,30 @@ end -- chulenxz = chunk length in 2 dimensions (xz) -- minposxz = minimum 2D position (xz) -- current layer = the layer for which to retrieve the map or nil to use multi_map's current layer -function multi_map.get_global_2dmap_flat(name, chulenxz, minposxz, current_layer) +function multi_map.get_global_2dmap_flat(name, chulenxz, minposxz, layer) if not multi_map.global_2d_map_arrays[name] then minetest.log("error", "[multi_map] Trying to get an unregistered global 2D map") end + if multi_map.wrap_layers then + if layer then + map_cache[name] = multi_map.get_mixed_2dnoise_flat(name, chulenxz, minposxz, layer) + else + map_cache[name] = multi_map.get_mixed_2dnoise_flat(name, chulenxz, minposxz, multi_map.current_layer) + end + end + if not map_cache[name] then - if not current_layer then + if not layer then if multi_map.current_layer ~= last_used_layer then multi_map.global_2d_maps[name] = minetest.get_perlin_map(multi_map.global_2d_params[name][multi_map.current_layer], chulenxz) end map_cache[name] = multi_map.global_2d_maps[name]:get2dMap_flat(minposxz, multi_map.global_2d_map_arrays[name][multi_map.current_layer]) - return map_cache[name] else - if current_layer ~= last_used_layer then - multi_map.global_2d_maps[name] = minetest.get_perlin_map(multi_map.global_2d_params[name][current_layer], chulenxz) + if layer ~= last_used_layer then + multi_map.global_2d_maps[name] = minetest.get_perlin_map(multi_map.global_2d_params[name][layer], chulenxz) end - map_cache[name] = multi_map.global_2d_maps[name]:get2dMap_flat(minposxz, multi_map.global_2d_map_arrays[name][current_layer]) + map_cache[name] = multi_map.global_2d_maps[name]:get2dMap_flat(minposxz, multi_map.global_2d_map_arrays[name][layer]) end end @@ -405,11 +420,18 @@ minetest.register_on_generated(function(minp, maxp) local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) local vm_data = vm:get_data() - multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.node[multi_map.bedrock]) + local skip = false + if multi_map.override_bedrock_generator then + skip = multi_map.override_bedrock_generator(multi_map.current_layer, vm, area, vm_data, minp, maxp, offset_minp, offset_maxp) + end - vm:set_data(vm_data) - vm:calc_lighting(false) - vm:write_to_map(false) + if not skip then + 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 elseif multi_map.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 @@ -419,12 +441,19 @@ minetest.register_on_generated(function(minp, maxp) local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) local vm_data = vm:get_data() - multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.node[multi_map.skyrock]) + local skip = false + if multi_map.override_skyrock_generator then + skip = multi_map.override_skyrock_generator(multi_map.current_layer, vm, area, vm_data, minp, maxp, offset_minp, offset_maxp) + end - vm:set_lighting({day=15, night=0}) - vm:set_data(vm_data) - vm:calc_lighting(false) - vm:write_to_map(false) + if not skip then + 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 else local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") local area = VoxelArea:new({MinEdge = emin, MaxEdge = emax}) @@ -432,7 +461,7 @@ minetest.register_on_generated(function(minp, maxp) local remove_shadow_caster = false -- Add a temporary stone layer above the chunk to ensure caves are dark - if multi_map.get_absolute_centerpoint() >= maxp.y then + if multi_map.generate_shadow_caster and multi_map.get_absolute_centerpoint() >= maxp.y 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"]) diff --git a/multi_map_core/debug.lua b/multi_map_core/debug.lua index 118cc50..ffb1009 100644 --- a/multi_map_core/debug.lua +++ b/multi_map_core/debug.lua @@ -5,6 +5,7 @@ function multi_map.log_state() minetest.log("action", "[multi_map] - Number of layers: "..multi_map.number_of_layers) minetest.log("action", "[multi_map] - Layers start at: "..(multi_map.map_min + multi_map.layers_start)) minetest.log("action", "[multi_map] - Layer height: "..multi_map.layer_height) + minetest.log("action", "[multi_map] - Wrap layers: "..tostring(multi_map.wrap_layers)) minetest.log("action", "[multi_map] - HUD enabled: "..tostring(multi_map.hud.enabled)) minetest.log("action", "[multi_map]") diff --git a/multi_map_core/init.lua b/multi_map_core/init.lua index 874722d..2af67b9 100644 --- a/multi_map_core/init.lua +++ b/multi_map_core/init.lua @@ -10,6 +10,7 @@ local multi_map_core_path = minetest.get_modpath("multi_map_core") -- The various sourced files contain the remainder of the API, the -- settings, node definitions and other core/ helper functionality dofile(multi_map_core_path.."/core.lua") +dofile(multi_map_core_path.."/noise_mixer.lua") dofile(multi_map_core_path.."/debug.lua") dofile(multi_map_core_path.."/nodes.lua") dofile(multi_map_core_path.."/hud.lua") diff --git a/multi_map_core/noise_mixer.lua b/multi_map_core/noise_mixer.lua new file mode 100644 index 0000000..fd38dd4 --- /dev/null +++ b/multi_map_core/noise_mixer.lua @@ -0,0 +1,204 @@ +multi_map.world_edge = { + NEGATIVE_X = 1, + POSITIVE_X = 2, + NEGATIVE_Z = 3, + POSITIVE_Z = 4, +} + +multi_map.linked_layers = {} + +function multi_map.register_linked_layer(source_layer, edge, target_layer, link_back) + if not multi_map.linked_layers[source_layer] then + multi_map.linked_layers[source_layer] = {} + end + + if not multi_map.linked_layers[target_layer] then + multi_map.linked_layers[target_layer] = {} + end + + if link_back == nil then + link_back = true + end + + if multi_map.world_edge.NEGATIVE_X == edge then + multi_map.linked_layers[source_layer][multi_map.world_edge.NEGATIVE_X] = target_layer + if link_back then + multi_map.linked_layers[target_layer][multi_map.world_edge.POSITIVE_X] = source_layer + end + elseif multi_map.world_edge.POSITIVE_X == edge then + multi_map.linked_layers[source_layer][multi_map.world_edge.POSITIVE_X] = target_layer + if link_back then + multi_map.linked_layers[target_layer][multi_map.world_edge.NEGATIVE_X] = source_layer + end + elseif multi_map.world_edge.NEGATIVE_Z == edge then + multi_map.linked_layers[source_layer][multi_map.world_edge.NEGATIVE_Z] = target_layer + if link_back then + multi_map.linked_layers[target_layer][multi_map.world_edge.POSITIVE_Z] = source_layer + end + elseif multi_map.world_edge.POSITIVE_Z == edge then + multi_map.linked_layers[source_layer][multi_map.world_edge.POSITIVE_Z] = target_layer + if link_back then + multi_map.linked_layers[target_layer][multi_map.world_edge.NEGATIVE_Z] = source_layer + end + end + +end + +function multi_map.get_linked_layer(layer, edge) + if multi_map.linked_layers[layer] then + return multi_map.linked_layers[layer][edge] + end +end + +function multi_map.get_which_world_edge(pos) + + if pos.x < -30912 + 160 then + return multi_map.world_edge.NEGATIVE_X + elseif pos.x > 30927 - 160 then + return multi_map.world_edge.POSITIVE_X + elseif pos.y < -30912 + 160 then + return multi_map.world_edge.NEGATIVE_Z + elseif pos.y > 30927 - 160 then + return multi_map.world_edge.POSITIVE_Z + else + return nil + end + +end + +function multi_map.in_mixing_area(pos) + if pos.x < -30912 + 160 or pos.x > 30927 - 160 or + pos.y < -30912 + 160 or pos.y > 30927 - 160 then + return true + else + return false + end +end + +function multi_map.in_mirrored_area(pos) + if pos.x < -30912 + 80 or pos.x > 30927 - 80 or + pos.y < -30912 + 80 or pos.y > 30927 - 80 then + return true + else + return false + end +end + +-- Current +-- 160 80 +-- [ ] [ ] +-- [ L ] [ M ] +-- [ ] [ ] +-- Opposite +-- 0 80 +-- [ ] [ ] +-- [ L ] [ M ] +-- [ ] [ ] +function multi_map.get_mixed_2dnoise_flat(name, chulenxz, minposxz, layer) + local edge = multi_map.get_which_world_edge(minposxz) + + if edge == nil then + return + end + + local target_layer = multi_map.get_linked_layer(layer, edge) + + if not target_layer then + return nil + end + + local opposite_minposxz = { x = minposxz.x, y = minposxz.y } + + if multi_map.in_mirrored_area(minposxz) then + if multi_map.world_edge.NEGATIVE_X == edge then + opposite_minposxz.x = 30927 - 160 + elseif multi_map.world_edge.POSITIVE_X == edge then + opposite_minposxz.x = -30912 + 160 + elseif multi_map.world_edge.NEGATIVE_Z == edge then + opposite_minposxz.y = 30927 - 160 + elseif multi_map.world_edge.POSITIVE_Z == edge then + opposite_minposxz.y = -30912 + 160 + end + + local noise1 = minetest.get_perlin_map(multi_map.global_2d_params[name][layer], chulenxz) + local noise2 = minetest.get_perlin_map(multi_map.global_2d_params[name][target_layer], chulenxz) + local map1 = noise1:get2dMap_flat(minposxz) + local map2 = noise2:get2dMap_flat(opposite_minposxz) + + if multi_map.world_edge.NEGATIVE_X == edge then + return multi_map.mix_noise_map_x(map1, map2, opposite_minposxz) + elseif multi_map.world_edge.POSITIVE_X == edge then + return multi_map.mix_noise_map_x(map2, map1, opposite_minposxz) + elseif multi_map.world_edge.NEGATIVE_Z == edge then + return multi_map.mix_noise_map_z(map1, map2, opposite_minposxz) + elseif multi_map.world_edge.POSITIVE_Z == edge then + return multi_map.mix_noise_map_x(map2, map1, opposite_minposxz) + end + + elseif multi_map.in_mixing_area(minposxz) then + if multi_map.world_edge.NEGATIVE_X == edge then + opposite_minposxz.x = 30927 - 80 + elseif multi_map.world_edge.POSITIVE_X == edge then + opposite_minposxz.x = -30912 + 80 + elseif multi_map.world_edge.NEGATIVE_Z == edge then + opposite_minposxz.y = 30927 - 80 + elseif multi_map.world_edge.POSITIVE_Z == edge then + opposite_minposxz.y = -30912 + 80 + end + + local noise1 = minetest.get_perlin_map(multi_map.global_2d_params[name][layer], chulenxz) + local noise2 = minetest.get_perlin_map(multi_map.global_2d_params[name][target_layer], chulenxz) + local map1 = noise1:get2dMap_flat(minposxz) + local map2 = noise2:get2dMap_flat(opposite_minposxz) + + if multi_map.world_edge.NEGATIVE_X == edge then + return multi_map.mix_noise_map_x(map2, map1, minposxz) + elseif multi_map.world_edge.POSITIVE_X == edge then + return multi_map.mix_noise_map_x(map1, map2, minposxz) + elseif multi_map.world_edge.NEGATIVE_Z == edge then + return multi_map.mix_noise_map_z(map2, map1, minposxz) + elseif multi_map.world_edge.POSITIVE_Z == edge then + return multi_map.mix_noise_map_x(map1, map2, minposxz) + end + else + return nil + end + +end + +function multi_map.mix_noise_map_x(map1, map2, minposxz) + + local new_map = {} + local nixz = 1 + + for y = minposxz.y, minposxz.y + 79 do + local weight_index = 1 + for x = minposxz.x, minposxz.x + 79 do + new_map[nixz] = ( map1[nixz] * (1 - (weight_index / 80)) ) + ( map2[nixz] * (weight_index / 80) ) + nixz = nixz + 1 + weight_index = weight_index + 1 + end + end + + return new_map + +end + +function multi_map.mix_noise_map_z(map1, map2, minposxz) + + local new_map = {} + local nixz = 1 + + for y = minposxz.y, minposxz.y + 80 do + local weight_index = 1 + for x = minposxz.x, minposxz.x + 80 do + new_map[nixz] = ( map1[nixz] * (1 - (weight_index / 160)) ) + ( map2[nixz] * (weight_index / 160) ) + nixz = nixz + 1 + end + weight_index = weight_index + 1 + nixz = nixz - 80 + end + + return new_map + +end diff --git a/multi_map_generators/init.lua b/multi_map_generators/init.lua index 6787196..3f14ee3 100644 --- a/multi_map_generators/init.lua +++ b/multi_map_generators/init.lua @@ -3,7 +3,7 @@ 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") +dofile(multi_map_generators_path.."/mmgen_testauri.lua") --multi_map.register_fallback_generator("Default Simple", mmgen_simple.generate) --multi_map.register_generator(9, mmgen_simple.generate, "default:sandstone") @@ -16,8 +16,19 @@ dofile(multi_map_generators_path.."/mmgen_simple.lua") multi_map.number_of_layers = 38 multi_map.layers_start_chunk = 0 multi_map.layer_height_chunks = 20 +multi_map.wrap_layers = true -multi_map.register_fallback_generator("Default Levels", mmgen_levels.generate) -multi_map.register_generator(19, mmgen_levels.generate) -multi_map.set_layer_name(19, "Central Layer") -multi_map.set_layer_name(20, "Remote Levels Land") +multi_map.register_fallback_generator(mmgen_simple.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) + +--multi_map.register_linked_layer(19, multi_map.world_edge.POSITIVE_X, 20, true) +--multi_map.register_linked_layer(19, multi_map.world_edge.NEGATIVE_X, 18, true) + +--multi_map.register_generator(9, mmgen_simple.generate, { nodetype = "default:sandstone", height = 0 }) +--multi_map.register_generator(9, mmgen_simple.generate, { nodetype = "default:sandstone", height = 1 }) +--multi_map.register_fallback_generator("Default Levels", mmgen_levels.generate) +--multi_map.register_generator(19, mmgen_levels.generate) +--multi_map.set_layer_name(19, "Central Layer") +--multi_map.set_layer_name(20, "Remote Levels Land") diff --git a/multi_map_generators/mmgen_simple.lua b/multi_map_generators/mmgen_simple.lua index 5552210..bd15bc2 100644 --- a/multi_map_generators/mmgen_simple.lua +++ b/multi_map_generators/mmgen_simple.lua @@ -1,6 +1,10 @@ mmgen_simple = {} -function mmgen_simple.generate(current_layer, vm, area, vm_data, minp, maxp, offset_minp, offset_maxp, nodetype) +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 c_ground if nodetype then c_ground = multi_map.node[nodetype] @@ -8,7 +12,7 @@ function mmgen_simple.generate(current_layer, vm, area, vm_data, minp, maxp, off c_ground = multi_map.node["default:stone"] end - if offset_minp.y >= 0 then + if offset_minp.y >= height then multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, multi_map.node["air"]) else multi_map.generate_singlenode_chunk(minp, maxp, area, vm_data, c_ground) diff --git a/multi_map_generators/mmgen_testauri.lua b/multi_map_generators/mmgen_testauri.lua index 6394fcd..943c6e6 100644 --- a/multi_map_generators/mmgen_testauri.lua +++ b/multi_map_generators/mmgen_testauri.lua @@ -93,6 +93,7 @@ local perlin_worm_start_params = { function mmgen_testauri.generate(current_layer, vm, area, vm_data, 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