From 2f6242e04f9d70234b4195d0de0936f21a0044d1 Mon Sep 17 00:00:00 2001 From: kay27 Date: Tue, 1 Feb 2022 03:11:53 +0400 Subject: [PATCH 1/4] Fix biomes 1/3 --- mods/CORE/mcl_mapgen/init.lua | 23 +- mods/MAPGEN/mcl_mapgen_core/biomes.lua | 46 ++++ mods/MAPGEN/mcl_mapgen_core/init.lua | 301 +++++-------------------- mods/MAPGEN/mcl_mapgen_core/light.lua | 27 +++ mods/MAPGEN/mcl_mapgen_core/nether.lua | 80 +++++++ mods/MAPGEN/mcl_mapgen_core/v6.lua | 36 +++ 6 files changed, 261 insertions(+), 252 deletions(-) create mode 100644 mods/MAPGEN/mcl_mapgen_core/biomes.lua create mode 100644 mods/MAPGEN/mcl_mapgen_core/light.lua create mode 100644 mods/MAPGEN/mcl_mapgen_core/nether.lua create mode 100644 mods/MAPGEN/mcl_mapgen_core/v6.lua diff --git a/mods/CORE/mcl_mapgen/init.lua b/mods/CORE/mcl_mapgen/init.lua index aa2630411..9a0fcf196 100644 --- a/mods/CORE/mcl_mapgen/init.lua +++ b/mods/CORE/mcl_mapgen/init.lua @@ -52,13 +52,14 @@ local seed = minetest.get_mapgen_setting("seed") mcl_mapgen.seed = seed mcl_mapgen.name = minetest.get_mapgen_setting("mg_name") mcl_mapgen.v6 = mcl_mapgen.name == "v6" -mcl_mapgen.superflat = mcl_mapgen.name == "flat" and minetest.get_mapgen_setting("mcl_superflat_classic") == "true" +mcl_mapgen.flat = mcl_mapgen.name == "flat" +mcl_mapgen.superflat = mcl_mapgen.flat and minetest.get_mapgen_setting("mcl_superflat_classic") == "true" mcl_mapgen.singlenode = mcl_mapgen.name == "singlenode" mcl_mapgen.normal = not mcl_mapgen.superflat and not mcl_mapgen.singlenode -local superflat, singlenode, normal = mcl_mapgen.superflat, mcl_mapgen.singlenode, mcl_mapgen.normal +local flat, superflat, singlenode, normal = mcl_mapgen.flat, mcl_mapgen.superflat, mcl_mapgen.singlenode, mcl_mapgen.normal -minetest_log("action", "[mcl_mapgen] Mapgen mode: " .. (normal and "normal" or (superflat and "superflat" or "singlenode"))) ----------------------------------------------------------------------------------------------------------------------------- +minetest_log("action", "[mcl_mapgen] Mapgen mode: " .. (normal and "normal" or (superflat and "superflat" or (flat and "flat" or "singlenode")))) +------------------------------------------------------------------------------------------------------------------------------------------------- -- Generator queues local queue_unsafe_engine = {} @@ -430,14 +431,12 @@ else nether.bedrock_top_min = nether.bedrock_top_max nether.lava_max = nether.min + 2 end -if mcl_mapgen.name == "flat" then - if superflat then - nether.flat_floor = nether.bedrock_bottom_max + 4 - nether.flat_ceiling = nether.bedrock_bottom_max + 52 - else - nether.flat_floor = nether.lava_max + 4 - nether.flat_ceiling = nether.lava_max + 52 - end +if superflat then + nether.flat_floor = nether.bedrock_bottom_max + 4 + nether.flat_ceiling = nether.bedrock_bottom_max + 52 +elseif flat then + nether.flat_floor = nether.lava_max + 4 + nether.flat_ceiling = nether.lava_max + 52 end -- The End (surface at ca. Y = -27000) diff --git a/mods/MAPGEN/mcl_mapgen_core/biomes.lua b/mods/MAPGEN/mcl_mapgen_core/biomes.lua new file mode 100644 index 000000000..955c73a90 --- /dev/null +++ b/mods/MAPGEN/mcl_mapgen_core/biomes.lua @@ -0,0 +1,46 @@ +local c_dirt_with_grass_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow") +local c_top_snow = minetest.get_content_id("mcl_core:snow") +local c_snow_block = minetest.get_content_id("mcl_core:snowblock") + +mcl_mapgen.register_on_generated(function(vm_context) + local minp, maxp = vm_context.minp, vm_context.maxp + local min_y = minp.y + if min_y > mcl_mapgen.overworld.max or maxp.y < mcl_mapgen.overworld.min then return end + vm_context.param2_data = vm_context.param2_data or vm:get_param2_data(vm_context.lvm_param2_buffer) + vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object("biomemap") + local param2_data = vm_context.param2_data + local biomemap = vm_context.biomemap + local vm, data, area = vm_context.vm, vm_context.data, vm_context.area + + ----- Interactive block fixing section ----- + ----- The section to perform basic block overrides of the core mapgen generated world. ----- + + -- Snow and sand fixes. This code implements snow consistency + -- and fixes floating sand and cut plants. + -- A snowy grass block must be below a top snow or snow block at all times. + + -- Set param2 (=color) of grass blocks. + -- Clear snowy grass blocks without snow above to ensure consistency. + local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:dirt_with_grass", "mcl_core:dirt_with_grass_snow"}) + + -- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration: + local aream = VoxelArea:new({MinEdge={x=minp.x, y=min_y, z=minp.z}, MaxEdge={x=maxp.x, y=min_y, z=maxp.z}}) + for n=1, #nodes do + local n = nodes[n] + local p_pos = area:index(n.x, n.y, n.z) + local p_pos_above = area:index(n.x, n.y+1, n.z) + local b_pos = aream:index(n.x, min_y, n.z) + local bn = minetest.get_biome_name(biomemap[b_pos]) + if bn then + local biome = minetest.registered_biomes[bn] + if biome and biome._mcl_biome_type then + param2_data[p_pos] = biome._mcl_palette_index + vm_context.write_param2 = true + end + end + if data[p_pos] == c_dirt_with_grass_snow and p_pos_above and data[p_pos_above] ~= c_top_snow and data[p_pos_above] ~= c_snow_block then + data[p_pos] = c_dirt_with_grass + vm_context.write = true + end + end +end, 999999999) diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 88fa0dabf..403282deb 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -56,6 +56,7 @@ local mg_name = mcl_mapgen.name local superflat = mcl_mapgen.superflat local v6 = mcl_mapgen.v6 local singlenode = mcl_mapgen.singlenode +local flat = mcl_mapgen.flat -- Content IDs local c_bedrock = minetest.get_content_id("mcl_core:bedrock") @@ -63,7 +64,6 @@ local c_obsidian = minetest.get_content_id("mcl_core:obsidian") local c_stone = minetest.get_content_id("mcl_core:stone") local c_dirt = minetest.get_content_id("mcl_core:dirt") local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass") -local c_dirt_with_grass_snow = minetest.get_content_id("mcl_core:dirt_with_grass_snow") local c_sand = minetest.get_content_id("mcl_core:sand") --local c_sandstone = minetest.get_content_id("mcl_core:sandstone") local c_void = minetest.get_content_id("mcl_core:void") @@ -79,12 +79,7 @@ if minetest.get_modpath("mcl_nether") then } end ---local c_end_stone = minetest.get_content_id("mcl_end:end_stone") local c_realm_barrier = minetest.get_content_id("mcl_core:realm_barrier") -local c_top_snow = minetest.get_content_id("mcl_core:snow") -local c_snow_block = minetest.get_content_id("mcl_core:snowblock") -local c_clay = minetest.get_content_id("mcl_core:clay") ---local c_jungletree = minetest.get_content_id("mcl_core:jungletree") local c_air = minetest.CONTENT_AIR -- @@ -1338,268 +1333,94 @@ end -- lvm_used: Set to true if any node in this on_generated has been set before. -- -- returns true if any node was set and lvm_used otherwise -local function set_layers(data, area, content_id, check, min, max, minp, maxp, lvm_used, pr) +local function set_layers(vm_context, pr, min, max, content_id, check) + local minp, maxp = vm_context.minp, vm_context.maxp if (maxp.y >= min and minp.y <= max) then for y = math.max(min, minp.y), math.min(max, maxp.y) do for x = minp.x, maxp.x do for z = minp.z, maxp.z do - local p_pos = area:index(x, y, z) + local p_pos = vm_context.area:index(x, y, z) if check then if type(check) == "function" and check({x=x,y=y,z=z}, data[p_pos], pr) then - data[p_pos] = content_id - lvm_used = true + vm_context.data[p_pos] = content_id + vm_context.write = true elseif check == data[p_pos] then - data[p_pos] = content_id - lvm_used = true + vm_context.data[p_pos] = content_id + vm_context.write = true end else - data[p_pos] = content_id - lvm_used = true + vm_context.data[p_pos] = content_id + vm_context.write = true end end end end end - return lvm_used end --- Below the bedrock, generate air/void -local function basic_safe(vm_context) - local vm, data, emin, emax, area, minp, maxp, chunkseed, blockseed = vm_context.vm, vm_context.data, vm_context.emin, vm_context.emax, vm_context.area, vm_context.minp, vm_context.maxp, vm_context.chunkseed, vm_context.blockseed +---- Generate layers of air, void, etc +local air_layers = { + {mcl_mapgen.nether.max + 1, mcl_mapgen.nether.max + 128} -- on Nether Roof +} +if flat then + air_layers[#air_layers + 1] = {mcl_mapgen.nether.flat_floor, mcl_mapgen.nether.flat_ceiling} -- Flat Nether +end + +-- Realm barrier between the Overworld void and the End +local barrier_min = mcl_mapgen.realm_barrier_overworld_end_min +local barrier_max = mcl_mapgen.realm_barrier_overworld_end_max + +local void_layers = { + {mcl_mapgen.EDGE_MIN , mcl_mapgen.nether.min - 1 }, -- below Nether + {mcl_mapgen.nether.max + 129, mcl_mapgen.end_.min - 1 }, -- below End (above Nether) + {mcl_mapgen.end_.max + 1 , barrier_min - 1 }, -- below Realm Barrier, above End + {barrier_max + 1 , mcl_mapgen.overworld.min - 1}, -- below Overworld, above Realm Barrier +} + +local bedrock_layers = {} +if not singlelayer then + bedrock_layers = { + {mcl_mapgen.overworld.bedrock_min , mcl_mapgen.overworld.bedrock_max }, + {mcl_mapgen.nether.bedrock_bottom_min, mcl_mapgen.nether.bedrock_bottom_max}, + {mcl_mapgen.nether.bedrock_top_min , mcl_mapgen.nether.bedrock_top_max }, + } +end + +mcl_mapgen.register_mapgen_block_lvm(function(vm_context) + local vm, data, area, minp, maxp, chunkseed, blockseed = vm_context.vm, vm_context.data, vm_context.area, vm_context.minp, vm_context.maxp, vm_context.chunkseed, vm_context.blockseed vm_context.param2_data = vm_context.param2_data or vm:get_param2_data(vm_context.lvm_param2_buffer) local param2_data = vm_context.param2_data - - local lvm_used = false local pr = PseudoRandom(blockseed) - - -- The Void below the Nether: - lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.EDGE_MIN , mcl_mapgen.nether.min -1, minp, maxp, lvm_used, pr) - - -- [[ THE NETHER: mcl_mapgen.nether.min mcl_mapgen.nether.max ]] - - -- The Air on the Nether roof, https://git.minetest.land/MineClone2/MineClone2/issues/1186 - lvm_used = set_layers(data, area, c_air , nil, mcl_mapgen.nether.max +1, mcl_mapgen.nether.max + 128 , minp, maxp, lvm_used, pr) - -- The Void above the Nether below the End: - lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.nether.max + 128 +1, mcl_mapgen.end_.min -1, minp, maxp, lvm_used, pr) - - -- [[ THE END: mcl_mapgen.end_.min mcl_mapgen.end_.max ]] - - -- The Void above the End below the Realm barrier: - lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.end_.max +1, mcl_mapgen.realm_barrier_overworld_end_min-1, minp, maxp, lvm_used, pr) - -- Realm barrier between the Overworld void and the End - lvm_used = set_layers(data, area, c_realm_barrier, nil, mcl_mapgen.realm_barrier_overworld_end_min , mcl_mapgen.realm_barrier_overworld_end_max , minp, maxp, lvm_used, pr) - -- The Void above Realm barrier below the Overworld: - lvm_used = set_layers(data, area, c_void , nil, mcl_mapgen.realm_barrier_overworld_end_max+1, mcl_mapgen.overworld.min -1, minp, maxp, lvm_used, pr) - - + for _, layer in pairs(void_layers) do + set_layers(vm_context, pr, layer[1], layer[2], c_void) + end + for _, layer in pairs(air_layers) do + set_layers(vm_context, pr, layer[1], layer[2], c_air) + end + set_layers(vm_context, pr, barrier_min, barrier_max, c_realm_barrier) + for _, layer in pairs(bedrock_layers) do + set_layers(vm_context, pr, layer[1], layer[2], c_bedrock, bedrock_check) + end if not singlenode then - -- Bedrock - lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_mapgen.overworld.bedrock_min, mcl_mapgen.overworld.bedrock_max, minp, maxp, lvm_used, pr) - lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_mapgen.nether.bedrock_bottom_min, mcl_mapgen.nether.bedrock_bottom_max, minp, maxp, lvm_used, pr) - lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_mapgen.nether.bedrock_top_min, mcl_mapgen.nether.bedrock_top_max, minp, maxp, lvm_used, pr) - - -- Flat Nether - if mg_name == "flat" then - lvm_used = set_layers(data, area, c_air, nil, mcl_mapgen.nether.flat_floor, mcl_mapgen.nether.flat_ceiling, minp, maxp, lvm_used, pr) - end - -- Big lava seas by replacing air below a certain height if mcl_mapgen.lava then - lvm_used = set_layers(data, area, c_lava, c_air, mcl_mapgen.overworld.min, mcl_mapgen.overworld.lava_max, minp, maxp, lvm_used, pr) + set_layers(vm_context, pr, mcl_mapgen.overworld.min, mcl_mapgen.overworld.lava_max, c_lava, c_air) if c_nether then - lvm_used = set_layers(data, area, c_nether.lava, c_air, mcl_mapgen.nether.min, mcl_mapgen.nether.lava_max, minp, maxp, lvm_used, pr) - end - end - - vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object("biomemap") - local biomemap = vm_context.biomemap - - ----- Interactive block fixing section ----- - ----- The section to perform basic block overrides of the core mapgen generated world. ----- - - -- Snow and sand fixes. This code implements snow consistency - -- and fixes floating sand and cut plants. - -- A snowy grass block must be below a top snow or snow block at all times. - if minp.y <= mcl_mapgen.overworld.max and maxp.y >= mcl_mapgen.overworld.min then - -- v6 mapgen: - if v6 then - - --[[ Remove broken double plants caused by v6 weirdness. - v6 might break the bottom part of double plants because of how it works. - There are 3 possibilities: - 1) Jungle: Top part is placed on top of a jungle tree or fern (=v6 jungle grass). - This is because the schematic might be placed even if some nodes of it - could not be placed because the destination was already occupied. - TODO: A better fix for this would be if schematics could abort placement - altogether if ANY of their nodes could not be placed. - 2) Cavegen: Removes the bottom part, the upper part floats - 3) Mudflow: Same as 2) ]] - local plants = minetest.find_nodes_in_area(minp, maxp, "group:double_plant") - for n = 1, #plants do - local node = vm:get_node_at(plants[n]) - local is_top = minetest.get_item_group(node.name, "double_plant") == 2 - if is_top then - local p_pos = area:index(plants[n].x, plants[n].y-1, plants[n].z) - if p_pos then - node = vm:get_node_at({x=plants[n].x, y=plants[n].y-1, z=plants[n].z}) - local is_bottom = minetest.get_item_group(node.name, "double_plant") == 1 - if not is_bottom then - p_pos = area:index(plants[n].x, plants[n].y, plants[n].z) - data[p_pos] = c_air - lvm_used = true - end - end - end - end - - - -- Non-v6 mapgens: - else - -- Set param2 (=color) of grass blocks. - -- Clear snowy grass blocks without snow above to ensure consistency. - local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:dirt_with_grass", "mcl_core:dirt_with_grass_snow"}) - - -- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration: - local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}}) - for n=1, #nodes do - local n = nodes[n] - local p_pos = area:index(n.x, n.y, n.z) - local p_pos_above = area:index(n.x, n.y+1, n.z) - --local p_pos_below = area:index(n.x, n.y-1, n.z) - local b_pos = aream:index(n.x, 0, n.z) - local bn = minetest.get_biome_name(biomemap[b_pos]) - if bn then - local biome = minetest.registered_biomes[bn] - if biome and biome._mcl_biome_type then - param2_data[p_pos] = biome._mcl_palette_index - vm_context.write_param2 = true - end - end - if data[p_pos] == c_dirt_with_grass_snow and p_pos_above and data[p_pos_above] ~= c_top_snow and data[p_pos_above] ~= c_snow_block then - data[p_pos] = c_dirt_with_grass - lvm_used = true - end - end - - end - - -- Nether block fixes: - -- * Replace water with Nether lava. - -- * Replace stone, sand dirt in v6 so the Nether works in v6. - elseif minp.y <= mcl_mapgen.nether.max and maxp.y >= mcl_mapgen.nether.min then - -- elseif emin.y <= mcl_mapgen.nether.max and emax.y >= mcl_mapgen.nether.min then - if c_nether then - if v6 then - -- local nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - for n=1, #nodes do - local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) - if data[p_pos] == c_water then - data[p_pos] = c_nether.lava - lvm_used = true - elseif data[p_pos] == c_stone then - data[p_pos] = c_netherrack - lvm_used = true - elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then - data[p_pos] = c_soul_sand - lvm_used = true - end - end - else - -- local nodes = minetest.find_nodes_in_area(emin, emax, {"group:water"}) - local nodes = minetest.find_nodes_in_area(minp, maxp, {"group:water"}) - for _, n in pairs(nodes) do - data[area:index(n.x, n.y, n.z)] = c_nether.lava - end - end - end - - -- End block fixes: - -- * Replace water with end stone or air (depending on height). - -- * Remove stone, sand, dirt in v6 so our End map generator works in v6. - -- * Generate spawn platform (End portal destination) - elseif minp.y <= mcl_mapgen.end_.max and maxp.y >= mcl_mapgen.end_.min then - local nodes - if v6 then - nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - -- nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - else - nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"}) - -- nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source"}) - end - if #nodes > 0 then - lvm_used = true - for _,n in pairs(nodes) do - data[area:index(n.x, n.y, n.z)] = c_air - end - end - - -- Obsidian spawn platform - if minp.y <= mcl_mapgen.end_.platform_pos.y and maxp.y >= mcl_mapgen.end_.platform_pos.y and - minp.x <= mcl_mapgen.end_.platform_pos.x and maxp.x >= mcl_mapgen.end_.platform_pos.z and - minp.z <= mcl_mapgen.end_.platform_pos.z and maxp.z >= mcl_mapgen.end_.platform_pos.z then - - --local pos1 = {x = math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), y = math.max(minp.y, mcl_mapgen.end_.platform_pos.y), z = math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2)} - --local pos2 = {x = math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2), y = math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2), z = math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2)} - - for x=math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2) do - for z=math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2), math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2) do - for y=math.max(minp.y, mcl_mapgen.end_.platform_pos.y), math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2) do - local p_pos = area:index(x, y, z) - if y == mcl_mapgen.end_.platform_pos.y then - data[p_pos] = c_obsidian - else - data[p_pos] = c_air - end - end - end - end - lvm_used = true + set_layers(vm_context, pr, mcl_mapgen.nether.min, mcl_mapgen.nether.lava_max, c_nether.lava, c_air) end end end - - - if not singlenode then - -- Generate special decorations - generate_underground_mushrooms(minp, maxp, blockseed) - generate_nether_decorations(minp, maxp, blockseed) - end - - vm_context.write = vm_context.write or lvm_used -end - -mcl_mapgen.register_mapgen_block_lvm(basic_safe, 1) +end, 1) local modpath = minetest.get_modpath(minetest.get_current_modname()) + dofile(modpath .. "/clay.lua") dofile(modpath .. "/tree_decoration.lua") dofile(modpath .. "/nether_wart.lua") - --- Nether Roof Light: -mcl_mapgen.register_mapgen_block_lvm(function(vm_context) - local minp = vm_context.minp - local miny = minp.y - if miny > mcl_mapgen.nether.max+127 then return end - local maxp = vm_context.maxp - local maxy = maxp.y - if maxy <= mcl_mapgen.nether.max then return end - local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.nether.max + 1), z = minp.z} - local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.nether.max + 127), z = maxp.z} - vm_context.vm:set_lighting({day=15, night=15}, p1, p2) - vm_context.write = true -end, 999999999) - --- End Light: -mcl_mapgen.register_mapgen_block_lvm(function(vm_context) - local minp = vm_context.minp - local miny = minp.y - if miny > mcl_mapgen.end_.max then return end - local maxp = vm_context.maxp - local maxy = maxp.y - if maxy <= mcl_mapgen.end_.min then return end - local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.end_.min), z = minp.z} - local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.end_.max), z = maxp.z} - vm_context.vm:set_lighting({day=15, night=15}, p1, p2) - vm_context.write = true -end, 9999999999) +dofile(modpath .. "/light.lua") +if v6 then + dofile(modpath .. "/v6.lua") +elseif not singlenode then + dofile(modpath .. "/biomes.lua") +end +-- dofile(modpath .. "/nether.lua") diff --git a/mods/MAPGEN/mcl_mapgen_core/light.lua b/mods/MAPGEN/mcl_mapgen_core/light.lua new file mode 100644 index 000000000..adf5029b9 --- /dev/null +++ b/mods/MAPGEN/mcl_mapgen_core/light.lua @@ -0,0 +1,27 @@ +-- Nether Roof Light: +mcl_mapgen.register_mapgen_block_lvm(function(vm_context) + local minp = vm_context.minp + local miny = minp.y + if miny > mcl_mapgen.nether.max+127 then return end + local maxp = vm_context.maxp + local maxy = maxp.y + if maxy <= mcl_mapgen.nether.max then return end + local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.nether.max + 1), z = minp.z} + local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.nether.max + 127), z = maxp.z} + vm_context.vm:set_lighting({day=15, night=15}, p1, p2) + vm_context.write = true +end, 999999999) + +-- End Light: +mcl_mapgen.register_mapgen_block_lvm(function(vm_context) + local minp = vm_context.minp + local miny = minp.y + if miny > mcl_mapgen.end_.max then return end + local maxp = vm_context.maxp + local maxy = maxp.y + if maxy <= mcl_mapgen.end_.min then return end + local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.end_.min), z = minp.z} + local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.end_.max), z = maxp.z} + vm_context.vm:set_lighting({day=15, night=15}, p1, p2) + vm_context.write = true +end, 9999999999) diff --git a/mods/MAPGEN/mcl_mapgen_core/nether.lua b/mods/MAPGEN/mcl_mapgen_core/nether.lua new file mode 100644 index 000000000..025232e5b --- /dev/null +++ b/mods/MAPGEN/mcl_mapgen_core/nether.lua @@ -0,0 +1,80 @@ + + -- Nether block fixes: + -- * Replace water with Nether lava. + -- * Replace stone, sand dirt in v6 so the Nether works in v6. + elseif minp.y <= mcl_mapgen.nether.max and maxp.y >= mcl_mapgen.nether.min then + if c_nether then + if v6 then + local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + for n=1, #nodes do + local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) + if data[p_pos] == c_water then + data[p_pos] = c_nether.lava + lvm_used = true + elseif data[p_pos] == c_stone then + data[p_pos] = c_netherrack + lvm_used = true + elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then + data[p_pos] = c_soul_sand + lvm_used = true + end + end + else + local nodes = minetest.find_nodes_in_area(minp, maxp, {"group:water"}) + for _, n in pairs(nodes) do + data[area:index(n.x, n.y, n.z)] = c_nether.lava + end + end + end + + -- End block fixes: + -- * Replace water with end stone or air (depending on height). + -- * Remove stone, sand, dirt in v6 so our End map generator works in v6. + -- * Generate spawn platform (End portal destination) + elseif minp.y <= mcl_mapgen.end_.max and maxp.y >= mcl_mapgen.end_.min then + local nodes + if v6 then + nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + else + nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"}) + end + if #nodes > 0 then + lvm_used = true + for _,n in pairs(nodes) do + data[area:index(n.x, n.y, n.z)] = c_air + end + end + + -- Obsidian spawn platform + if minp.y <= mcl_mapgen.end_.platform_pos.y and maxp.y >= mcl_mapgen.end_.platform_pos.y and + minp.x <= mcl_mapgen.end_.platform_pos.x and maxp.x >= mcl_mapgen.end_.platform_pos.z and + minp.z <= mcl_mapgen.end_.platform_pos.z and maxp.z >= mcl_mapgen.end_.platform_pos.z then + + --local pos1 = {x = math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), y = math.max(minp.y, mcl_mapgen.end_.platform_pos.y), z = math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2)} + --local pos2 = {x = math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2), y = math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2), z = math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2)} + + for x=math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2) do + for z=math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2), math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2) do + for y=math.max(minp.y, mcl_mapgen.end_.platform_pos.y), math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2) do + local p_pos = area:index(x, y, z) + if y == mcl_mapgen.end_.platform_pos.y then + data[p_pos] = c_obsidian + else + data[p_pos] = c_air + end + end + end + end + lvm_used = true + end + end + end + + + if not singlenode then + -- Generate special decorations + generate_underground_mushrooms(minp, maxp, blockseed) + generate_nether_decorations(minp, maxp, blockseed) + end + +end, 1) diff --git a/mods/MAPGEN/mcl_mapgen_core/v6.lua b/mods/MAPGEN/mcl_mapgen_core/v6.lua new file mode 100644 index 000000000..fb9ffcdbf --- /dev/null +++ b/mods/MAPGEN/mcl_mapgen_core/v6.lua @@ -0,0 +1,36 @@ +local c_air = minetest.CONTENT_AIR + +mcl_mapgen.register_on_generated(function(vm_context) + local minp, maxp = vm_context.minp, vm_context.maxp + if minp.y > mcl_mapgen.overworld.max or maxp.y < mcl_mapgen.overworld.min then return end + local vm, data, area = vm_context.vm, vm_context.data, vm_context.area + + --[[ Remove broken double plants caused by v6 weirdness. + v6 might break the bottom part of double plants because of how it works. + There are 3 possibilities: + 1) Jungle: Top part is placed on top of a jungle tree or fern (=v6 jungle grass). + This is because the schematic might be placed even if some nodes of it + could not be placed because the destination was already occupied. + TODO: A better fix for this would be if schematics could abort placement + altogether if ANY of their nodes could not be placed. + 2) Cavegen: Removes the bottom part, the upper part floats + 3) Mudflow: Same as 2) ]] + local plants = minetest.find_nodes_in_area(minp, maxp, "group:double_plant") + for n = 1, #plants do + local node = vm:get_node_at(plants[n]) + local is_top = minetest.get_item_group(node.name, "double_plant") == 2 + if is_top then + local p_pos = area:index(plants[n].x, plants[n].y-1, plants[n].z) + if p_pos then + node = vm:get_node_at({x=plants[n].x, y=plants[n].y-1, z=plants[n].z}) + local is_bottom = minetest.get_item_group(node.name, "double_plant") == 1 + if not is_bottom then + p_pos = area:index(plants[n].x, plants[n].y, plants[n].z) + data[p_pos] = c_air + vm_context.write = true + end + end + end + end + +end, 999999999) From 7b47e4d12bae69fe69c3343b6ade8916b12dd8b4 Mon Sep 17 00:00:00 2001 From: kay27 Date: Tue, 1 Feb 2022 04:44:05 +0400 Subject: [PATCH 2/4] Fix biomes 2/3 --- mods/CORE/mcl_mapgen/init.lua | 1 + mods/MAPGEN/mcl_mapgen_core/biomes.lua | 26 ++-- mods/MAPGEN/mcl_mapgen_core/init.lua | 101 +--------------- mods/MAPGEN/mcl_mapgen_core/nether.lua | 158 +++++++++++++++++++++---- 4 files changed, 151 insertions(+), 135 deletions(-) diff --git a/mods/CORE/mcl_mapgen/init.lua b/mods/CORE/mcl_mapgen/init.lua index 9a0fcf196..71442dbaf 100644 --- a/mods/CORE/mcl_mapgen/init.lua +++ b/mods/CORE/mcl_mapgen/init.lua @@ -264,6 +264,7 @@ minetest.register_on_generated(function(minp, maxp, chunkseed) end if #queue_unsafe_engine > 0 then + vm_context.minp, vm_context.maxp = minp, maxp for _, v in pairs(queue_unsafe_engine) do v.f(vm_context) end diff --git a/mods/MAPGEN/mcl_mapgen_core/biomes.lua b/mods/MAPGEN/mcl_mapgen_core/biomes.lua index 955c73a90..d50f4da56 100644 --- a/mods/MAPGEN/mcl_mapgen_core/biomes.lua +++ b/mods/MAPGEN/mcl_mapgen_core/biomes.lua @@ -4,14 +4,18 @@ local c_snow_block = minetest.get_content_id("mcl_core:snowblock") mcl_mapgen.register_on_generated(function(vm_context) local minp, maxp = vm_context.minp, vm_context.maxp - local min_y = minp.y - if min_y > mcl_mapgen.overworld.max or maxp.y < mcl_mapgen.overworld.min then return end + local min_y, max_y = minp.y, maxp.y + if min_y > mcl_mapgen.overworld.max or max_y < mcl_mapgen.overworld.min then return end + vm_context.param2_data = vm_context.param2_data or vm:get_param2_data(vm_context.lvm_param2_buffer) vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object("biomemap") local param2_data = vm_context.param2_data local biomemap = vm_context.biomemap local vm, data, area = vm_context.vm, vm_context.data, vm_context.area + local min_x, min_z = minp.x, minp.z + local chunksize = max_y - min_y + 1 + ----- Interactive block fixing section ----- ----- The section to perform basic block overrides of the core mapgen generated world. ----- @@ -23,16 +27,16 @@ mcl_mapgen.register_on_generated(function(vm_context) -- Clear snowy grass blocks without snow above to ensure consistency. local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:dirt_with_grass", "mcl_core:dirt_with_grass_snow"}) - -- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration: - local aream = VoxelArea:new({MinEdge={x=minp.x, y=min_y, z=minp.z}, MaxEdge={x=maxp.x, y=min_y, z=maxp.z}}) for n=1, #nodes do - local n = nodes[n] - local p_pos = area:index(n.x, n.y, n.z) - local p_pos_above = area:index(n.x, n.y+1, n.z) - local b_pos = aream:index(n.x, min_y, n.z) - local bn = minetest.get_biome_name(biomemap[b_pos]) - if bn then - local biome = minetest.registered_biomes[bn] + local pos = nodes[n] + local x, y, z = pos.x, pos.y, pos.z + local p_pos = area:index(x, y, z) + local p_pos_above = area:index(x, y + 1, z) + local biomemap_offset = (z - min_z) * chunksize + x - min_x + 1 + local biome_id = biomemap[biomemap_offset] + local biome_name = minetest.get_biome_name(biome_id) + if biome_name then + local biome = minetest.registered_biomes[biome_name] if biome and biome._mcl_biome_type then param2_data[p_pos] = biome._mcl_palette_index vm_context.write_param2 = true diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 403282deb..73699db1f 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -65,7 +65,6 @@ local c_stone = minetest.get_content_id("mcl_core:stone") local c_dirt = minetest.get_content_id("mcl_core:dirt") local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass") local c_sand = minetest.get_content_id("mcl_core:sand") ---local c_sandstone = minetest.get_content_id("mcl_core:sandstone") local c_void = minetest.get_content_id("mcl_core:void") local c_lava = minetest.get_content_id("mcl_core:lava_source") local c_water = minetest.get_content_id("mcl_core:water_source") @@ -1189,100 +1188,6 @@ function mcl_mapgen_core.generate_end_exit_portal(pos) portal_generated = true end --- Generate mushrooms in caves manually. --- Minetest's API does not support decorations in caves yet. :-( -local function generate_underground_mushrooms(minp, maxp, seed) - if not mcl_mushrooms then return end - - local pr_shroom = PseudoRandom(seed-24359) - -- Generate rare underground mushrooms - -- TODO: Make them appear in groups, use Perlin noise - local min, max = mcl_mapgen.overworld.lava_max + 4, 0 - if minp.y > max or maxp.y < min then - return - end - - local bpos - local stone = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_core:stone", "mcl_core:dirt", "mcl_core:mycelium", "mcl_core:podzol", "mcl_core:andesite", "mcl_core:diorite", "mcl_core:granite", "mcl_core:stone_with_coal", "mcl_core:stone_with_iron", "mcl_core:stone_with_gold"}) - - for n = 1, #stone do - bpos = {x = stone[n].x, y = stone[n].y + 1, z = stone[n].z } - - local l = minetest.get_node_light(bpos, 0.5) - if bpos.y >= min and bpos.y <= max and l and l <= 12 and pr_shroom:next(1,1000) < 4 then - if pr_shroom:next(1,2) == 1 then - minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"}) - else - minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"}) - end - end - end -end - --- Generate Nether decorations manually: Eternal fire, mushrooms --- Minetest's API does not support decorations in caves yet. :-( -local function generate_nether_decorations(minp, maxp, seed) - if c_nether == nil then - return - end - - local pr_nether = PseudoRandom(seed+667) - - if minp.y > mcl_mapgen.nether.max or maxp.y < mcl_mapgen.nether.min then - return - end - - minetest.log("action", "[mcl_mapgen_core] Nether decorations " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp)) - - -- TODO: Generate everything based on Perlin noise instead of PseudoRandom - - local bpos - local rack = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:netherrack"}) - local magma = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:magma"}) - local ssand = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:soul_sand"}) - - -- Helper function to spawn “fake” decoration - local function special_deco(nodes, spawn_func) - for n = 1, #nodes do - bpos = {x = nodes[n].x, y = nodes[n].y + 1, z = nodes[n].z } - - spawn_func(bpos) - end - - end - - -- Eternal fire on netherrack - special_deco(rack, function(bpos) - -- Eternal fire on netherrack - if pr_nether:next(1,100) <= 3 then - minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"}) - end - end) - - -- Eternal fire on magma cubes - special_deco(magma, function(bpos) - if pr_nether:next(1,150) == 1 then - minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"}) - end - end) - - -- Mushrooms on netherrack - -- Note: Spawned *after* the fire because of light level checks - if mcl_mushrooms then - special_deco(rack, function(bpos) - local l = minetest.get_node_light(bpos, 0.5) - if bpos.y > mcl_mapgen.nether.lava_max + 6 and l and l <= 12 and pr_nether:next(1,1000) <= 4 then - -- TODO: Make mushrooms appear in groups, use Perlin noise - if pr_nether:next(1,2) == 1 then - minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"}) - else - minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"}) - end - end - end) - end -end - -- Generate basic layer-based nodes: void, bedrock, realm barrier, lava seas, etc. -- Also perform some basic node replacements. @@ -1334,7 +1239,7 @@ end -- -- returns true if any node was set and lvm_used otherwise local function set_layers(vm_context, pr, min, max, content_id, check) - local minp, maxp = vm_context.minp, vm_context.maxp + local minp, maxp, data, area = vm_context.minp, vm_context.maxp, vm_context.data, vm_context.area if (maxp.y >= min and minp.y <= max) then for y = math.max(min, minp.y), math.min(max, maxp.y) do for x = minp.x, maxp.x do @@ -1342,10 +1247,10 @@ local function set_layers(vm_context, pr, min, max, content_id, check) local p_pos = vm_context.area:index(x, y, z) if check then if type(check) == "function" and check({x=x,y=y,z=z}, data[p_pos], pr) then - vm_context.data[p_pos] = content_id + data[p_pos] = content_id vm_context.write = true elseif check == data[p_pos] then - vm_context.data[p_pos] = content_id + data[p_pos] = content_id vm_context.write = true end else diff --git a/mods/MAPGEN/mcl_mapgen_core/nether.lua b/mods/MAPGEN/mcl_mapgen_core/nether.lua index 025232e5b..c2c1524e3 100644 --- a/mods/MAPGEN/mcl_mapgen_core/nether.lua +++ b/mods/MAPGEN/mcl_mapgen_core/nether.lua @@ -1,31 +1,137 @@ +local v6 = mcl_mapgen.v6 - -- Nether block fixes: - -- * Replace water with Nether lava. - -- * Replace stone, sand dirt in v6 so the Nether works in v6. - elseif minp.y <= mcl_mapgen.nether.max and maxp.y >= mcl_mapgen.nether.min then - if c_nether then - if v6 then - local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - for n=1, #nodes do - local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) - if data[p_pos] == c_water then - data[p_pos] = c_nether.lava - lvm_used = true - elseif data[p_pos] == c_stone then - data[p_pos] = c_netherrack - lvm_used = true - elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then - data[p_pos] = c_soul_sand - lvm_used = true - end - end +local mcl_mushrooms = minetest.get_modpath("mcl_mushrooms") + +local c_nether = minetest.get_modpath("mcl_nether") and { + soul_sand = minetest.get_content_id("mcl_nether:soul_sand"), + netherrack = minetest.get_content_id("mcl_nether:netherrack"), + lava = minetest.get_content_id("mcl_nether:nether_lava_source") +} + +-- Generate mushrooms in caves manually. +-- Minetest's API does not support decorations in caves yet. :-( +local function generate_underground_mushrooms(minp, maxp, seed) + if not mcl_mushrooms then return end + + local pr_shroom = PseudoRandom(seed-24359) + -- Generate rare underground mushrooms + -- TODO: Make them appear in groups, use Perlin noise + local min, max = mcl_mapgen.overworld.lava_max + 4, 0 + if minp.y > max or maxp.y < min then + return + end + + local bpos + local stone = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_core:stone", "mcl_core:dirt", "mcl_core:mycelium", "mcl_core:podzol", "mcl_core:andesite", "mcl_core:diorite", "mcl_core:granite", "mcl_core:stone_with_coal", "mcl_core:stone_with_iron", "mcl_core:stone_with_gold"}) + + for n = 1, #stone do + bpos = {x = stone[n].x, y = stone[n].y + 1, z = stone[n].z } + + local l = minetest.get_node_light(bpos, 0.5) + if bpos.y >= min and bpos.y <= max and l and l <= 12 and pr_shroom:next(1,1000) < 4 then + if pr_shroom:next(1,2) == 1 then + minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"}) + else + minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"}) + end + end + end +end + +-- Generate Nether decorations manually: Eternal fire, mushrooms +-- Minetest's API does not support decorations in caves yet. :-( +local function generate_nether_decorations(minp, maxp, seed) + if c_nether == nil then + return + end + + local pr_nether = PseudoRandom(seed+667) + + if minp.y > mcl_mapgen.nether.max or maxp.y < mcl_mapgen.nether.min then + return + end + + minetest.log("action", "[mcl_mapgen_core] Nether decorations " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp)) + + -- TODO: Generate everything based on Perlin noise instead of PseudoRandom + + local bpos + local rack = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:netherrack"}) + local magma = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:magma"}) + local ssand = minetest.find_nodes_in_area_under_air(minp, maxp, {"mcl_nether:soul_sand"}) + + -- Helper function to spawn “fake” decoration + local function special_deco(nodes, spawn_func) + for n = 1, #nodes do + bpos = {x = nodes[n].x, y = nodes[n].y + 1, z = nodes[n].z } + + spawn_func(bpos) + end + + end + + -- Eternal fire on netherrack + special_deco(rack, function(bpos) + -- Eternal fire on netherrack + if pr_nether:next(1,100) <= 3 then + minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"}) + end + end) + + -- Eternal fire on magma cubes + special_deco(magma, function(bpos) + if pr_nether:next(1,150) == 1 then + minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"}) + end + end) + + -- Mushrooms on netherrack + -- Note: Spawned *after* the fire because of light level checks + if mcl_mushrooms then + special_deco(rack, function(bpos) + local l = minetest.get_node_light(bpos, 0.5) + if bpos.y > mcl_mapgen.nether.lava_max + 6 and l and l <= 12 and pr_nether:next(1,1000) <= 4 then + -- TODO: Make mushrooms appear in groups, use Perlin noise + if pr_nether:next(1,2) == 1 then + minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"}) else - local nodes = minetest.find_nodes_in_area(minp, maxp, {"group:water"}) - for _, n in pairs(nodes) do - data[area:index(n.x, n.y, n.z)] = c_nether.lava - end + minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"}) end end + end) + end +end + +mcl_mapgen.register_mapgen(function(minp, maxp, seed, vm_context) + local min_y, max_y = minp.y, maxp.y + + -- Nether block fixes: + -- * Replace water with Nether lava. + -- * Replace stone, sand dirt in v6 so the Nether works in v6. + if min_y <= mcl_mapgen.nether.max and max_y >= mcl_mapgen.nether.min then + if c_nether then + if v6 then + local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + for n=1, #nodes do + local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) + if data[p_pos] == c_water then + data[p_pos] = c_nether.lava + lvm_used = true + elseif data[p_pos] == c_stone then + data[p_pos] = c_netherrack + lvm_used = true + elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then + data[p_pos] = c_soul_sand + lvm_used = true + end + end + else + local nodes = minetest.find_nodes_in_area(minp, maxp, {"group:water"}) + for _, n in pairs(nodes) do + data[area:index(n.x, n.y, n.z)] = c_nether.lava + end + end + end -- End block fixes: -- * Replace water with end stone or air (depending on height). @@ -73,8 +179,8 @@ if not singlenode then -- Generate special decorations - generate_underground_mushrooms(minp, maxp, blockseed) - generate_nether_decorations(minp, maxp, blockseed) + generate_underground_mushrooms(minp, maxp, chunkseed) + generate_nether_decorations(minp, maxp, chunkseed) end end, 1) From e023b9687799d1af3de9f4007c3cdf66b6d88116 Mon Sep 17 00:00:00 2001 From: kay27 Date: Tue, 1 Feb 2022 06:33:03 +0400 Subject: [PATCH 3/4] Fix biomes 3/3 --- mods/MAPGEN/mcl_mapgen_core/init.lua | 8 +- mods/MAPGEN/mcl_mapgen_core/light.lua | 16 +++- mods/MAPGEN/mcl_mapgen_core/nether.lua | 105 ++++++------------------- mods/MAPGEN/mcl_mapgen_core/v6.lua | 13 +++ 4 files changed, 56 insertions(+), 86 deletions(-) diff --git a/mods/MAPGEN/mcl_mapgen_core/init.lua b/mods/MAPGEN/mcl_mapgen_core/init.lua index 73699db1f..93c1f23bb 100644 --- a/mods/MAPGEN/mcl_mapgen_core/init.lua +++ b/mods/MAPGEN/mcl_mapgen_core/init.lua @@ -60,14 +60,10 @@ local flat = mcl_mapgen.flat -- Content IDs local c_bedrock = minetest.get_content_id("mcl_core:bedrock") -local c_obsidian = minetest.get_content_id("mcl_core:obsidian") -local c_stone = minetest.get_content_id("mcl_core:stone") local c_dirt = minetest.get_content_id("mcl_core:dirt") local c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass") -local c_sand = minetest.get_content_id("mcl_core:sand") local c_void = minetest.get_content_id("mcl_core:void") local c_lava = minetest.get_content_id("mcl_core:lava_source") -local c_water = minetest.get_content_id("mcl_core:water_source") local c_nether = nil if minetest.get_modpath("mcl_nether") then @@ -1328,4 +1324,6 @@ if v6 then elseif not singlenode then dofile(modpath .. "/biomes.lua") end --- dofile(modpath .. "/nether.lua") +if not singlenode and c_nether then + dofile(modpath .. "/nether.lua") +end diff --git a/mods/MAPGEN/mcl_mapgen_core/light.lua b/mods/MAPGEN/mcl_mapgen_core/light.lua index adf5029b9..a0b503352 100644 --- a/mods/MAPGEN/mcl_mapgen_core/light.lua +++ b/mods/MAPGEN/mcl_mapgen_core/light.lua @@ -1,3 +1,17 @@ +-- Nether Light: +mcl_mapgen.register_mapgen_block_lvm(function(vm_context) + local minp = vm_context.minp + local miny = minp.y + if miny > mcl_mapgen.nether.max then return end + local maxp = vm_context.maxp + local maxy = maxp.y + if maxy < mcl_mapgen.nether.min then return end + local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.nether.min), z = minp.z} + local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.nether.max), z = maxp.z} + vm_context.vm:set_lighting({day = 3, night = 4}, p1, p2) + vm_context.write = true +end, 999999999) + -- Nether Roof Light: mcl_mapgen.register_mapgen_block_lvm(function(vm_context) local minp = vm_context.minp @@ -8,7 +22,7 @@ mcl_mapgen.register_mapgen_block_lvm(function(vm_context) if maxy <= mcl_mapgen.nether.max then return end local p1 = {x = minp.x, y = math.max(miny, mcl_mapgen.nether.max + 1), z = minp.z} local p2 = {x = maxp.x, y = math.min(maxy, mcl_mapgen.nether.max + 127), z = maxp.z} - vm_context.vm:set_lighting({day=15, night=15}, p1, p2) + vm_context.vm:set_lighting({day = 15, night = 15}, p1, p2) vm_context.write = true end, 999999999) diff --git a/mods/MAPGEN/mcl_mapgen_core/nether.lua b/mods/MAPGEN/mcl_mapgen_core/nether.lua index c2c1524e3..1b05d32bf 100644 --- a/mods/MAPGEN/mcl_mapgen_core/nether.lua +++ b/mods/MAPGEN/mcl_mapgen_core/nether.lua @@ -2,11 +2,13 @@ local v6 = mcl_mapgen.v6 local mcl_mushrooms = minetest.get_modpath("mcl_mushrooms") -local c_nether = minetest.get_modpath("mcl_nether") and { - soul_sand = minetest.get_content_id("mcl_nether:soul_sand"), - netherrack = minetest.get_content_id("mcl_nether:netherrack"), - lava = minetest.get_content_id("mcl_nether:nether_lava_source") -} +local c_water = minetest.get_content_id("mcl_core:water_source") +local c_stone = minetest.get_content_id("mcl_core:stone") +local c_sand = minetest.get_content_id("mcl_core:sand") + +local c_soul_sand = minetest.get_content_id("mcl_nether:soul_sand") +local c_netherrack = minetest.get_content_id("mcl_nether:netherrack") +local c_nether_lava = minetest.get_content_id("mcl_nether:nether_lava_source") -- Generate mushrooms in caves manually. -- Minetest's API does not support decorations in caves yet. :-( @@ -41,10 +43,6 @@ end -- Generate Nether decorations manually: Eternal fire, mushrooms -- Minetest's API does not support decorations in caves yet. :-( local function generate_nether_decorations(minp, maxp, seed) - if c_nether == nil then - return - end - local pr_nether = PseudoRandom(seed+667) if minp.y > mcl_mapgen.nether.max or maxp.y < mcl_mapgen.nether.min then @@ -108,79 +106,26 @@ mcl_mapgen.register_mapgen(function(minp, maxp, seed, vm_context) -- Nether block fixes: -- * Replace water with Nether lava. -- * Replace stone, sand dirt in v6 so the Nether works in v6. - if min_y <= mcl_mapgen.nether.max and max_y >= mcl_mapgen.nether.min then - if c_nether then - if v6 then - local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - for n=1, #nodes do - local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) - if data[p_pos] == c_water then - data[p_pos] = c_nether.lava - lvm_used = true - elseif data[p_pos] == c_stone then - data[p_pos] = c_netherrack - lvm_used = true - elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then - data[p_pos] = c_soul_sand - lvm_used = true - end - end - else - local nodes = minetest.find_nodes_in_area(minp, maxp, {"group:water"}) - for _, n in pairs(nodes) do - data[area:index(n.x, n.y, n.z)] = c_nether.lava + if min_y > mcl_mapgen.nether.max or max_y < mcl_mapgen.nether.min then return end + if v6 then + local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + if #nodes < 1 then return end + vm_context.write = true + local data = vm_context.data + local area = vm_context.area + for n = 1, #nodes do + local p_pos = area:index(nodes[n].x, nodes[n].y, nodes[n].z) + if data[p_pos] == c_water then + data[p_pos] = c_nether_lava + elseif data[p_pos] == c_stone then + data[p_pos] = c_netherrack + elseif data[p_pos] == c_sand or data[p_pos] == c_dirt then + data[p_pos] = c_soul_sand end end - end - - -- End block fixes: - -- * Replace water with end stone or air (depending on height). - -- * Remove stone, sand, dirt in v6 so our End map generator works in v6. - -- * Generate spawn platform (End portal destination) - elseif minp.y <= mcl_mapgen.end_.max and maxp.y >= mcl_mapgen.end_.min then - local nodes - if v6 then - nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) - else - nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source"}) - end - if #nodes > 0 then - lvm_used = true - for _,n in pairs(nodes) do - data[area:index(n.x, n.y, n.z)] = c_air - end - end - - -- Obsidian spawn platform - if minp.y <= mcl_mapgen.end_.platform_pos.y and maxp.y >= mcl_mapgen.end_.platform_pos.y and - minp.x <= mcl_mapgen.end_.platform_pos.x and maxp.x >= mcl_mapgen.end_.platform_pos.z and - minp.z <= mcl_mapgen.end_.platform_pos.z and maxp.z >= mcl_mapgen.end_.platform_pos.z then - - --local pos1 = {x = math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), y = math.max(minp.y, mcl_mapgen.end_.platform_pos.y), z = math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2)} - --local pos2 = {x = math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2), y = math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2), z = math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2)} - - for x=math.max(minp.x, mcl_mapgen.end_.platform_pos.x-2), math.min(maxp.x, mcl_mapgen.end_.platform_pos.x+2) do - for z=math.max(minp.z, mcl_mapgen.end_.platform_pos.z-2), math.min(maxp.z, mcl_mapgen.end_.platform_pos.z+2) do - for y=math.max(minp.y, mcl_mapgen.end_.platform_pos.y), math.min(maxp.y, mcl_mapgen.end_.platform_pos.y+2) do - local p_pos = area:index(x, y, z) - if y == mcl_mapgen.end_.platform_pos.y then - data[p_pos] = c_obsidian - else - data[p_pos] = c_air - end - end - end - end - lvm_used = true - end - end - end - - - if not singlenode then - -- Generate special decorations - generate_underground_mushrooms(minp, maxp, chunkseed) - generate_nether_decorations(minp, maxp, chunkseed) + else end + generate_underground_mushrooms(minp, maxp, seed) + generate_nether_decorations(minp, maxp, seed) end, 1) diff --git a/mods/MAPGEN/mcl_mapgen_core/v6.lua b/mods/MAPGEN/mcl_mapgen_core/v6.lua index fb9ffcdbf..19fd44647 100644 --- a/mods/MAPGEN/mcl_mapgen_core/v6.lua +++ b/mods/MAPGEN/mcl_mapgen_core/v6.lua @@ -2,6 +2,19 @@ local c_air = minetest.CONTENT_AIR mcl_mapgen.register_on_generated(function(vm_context) local minp, maxp = vm_context.minp, vm_context.maxp + + if minp.y <= mcl_mapgen.end_.max and maxp.y >= mcl_mapgen.end_.min then + local nodes = minetest.find_nodes_in_area(minp, maxp, {"mcl_core:water_source", "mcl_core:stone", "mcl_core:sand", "mcl_core:dirt"}) + if #nodes > 0 then + for _, n in pairs(nodes) do + data[area:index(n.x, n.y, n.z)] = c_air + end + end + vm_context.write = true + return + end + + if minp.y > mcl_mapgen.overworld.max or maxp.y < mcl_mapgen.overworld.min then return end local vm, data, area = vm_context.vm, vm_context.data, vm_context.area From e10715aa590a98782b21927d33192bcf22af09bd Mon Sep 17 00:00:00 2001 From: kay27 Date: Tue, 1 Feb 2022 06:36:19 +0400 Subject: [PATCH 4/4] Fix mapgen API.md --- mods/CORE/mcl_mapgen/API.md | 151 ++++++++++++++++++++---------------- 1 file changed, 85 insertions(+), 66 deletions(-) diff --git a/mods/CORE/mcl_mapgen/API.md b/mods/CORE/mcl_mapgen/API.md index 23365b357..d489b3ad5 100644 --- a/mods/CORE/mcl_mapgen/API.md +++ b/mods/CORE/mcl_mapgen/API.md @@ -1,101 +1,120 @@ # mcl_mapgen -============ +------------ Helps to avoid problems caused by 'chunk-in-shell' feature of mapgen.cpp. + It also queues your generators to run them in proper order: ### mcl_mapgen.register_on_generated(lvm_callback_function, order_number) -========================================================================= +------------------------------------------------------------------------- Replacement of engine API function `minetest.register_on_generated(function(vm_context))` + It is still unsafe. Cavegen part can and will overwrite outer 1-block layer of the chunk which is expected to be generated. + Nodes marked as `is_ground_content` could be overwritten. Air and water are usually 'ground content' too. For Minetest 5.4 it doesn't recommended to place blocks within lvm callback function. + See https://git.minetest.land/MineClone2/MineClone2/issues/1395 - `lvm_callback_function`: chunk callback LVM function definition: - `function(vm_context)`: - `vm_context` will pass into next lvm callback function from the queue! - `vm_context`: a table which already contains some LVM data as the fields, and some of them can be added in your lvm callback function: - `vm`: curent voxel manipulator object itself; - `chunkseed`: seed of this mapchunk; - `minp` & `maxp`: minimum and maximum chunk position; - `emin` & `emax`: minimum and maximum chunk position WITH SHELL AROUND IT; - `area`: voxel area, can be helpful to access data; - `data`: LVM buffer data array, data loads into it before the callbacks; - `write`: set it to true in your lvm callback functionm, if you changed `data` and want to write it; - `param2_data`: LVM buffer data array of `param2`, !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourself: - `vm_context.param2_data = vm_context.param2_data or vm_context.vm:get_param2_data(vm_context.lvm_param2_buffer)` - `write_param2`: set it to true in your lvm callback function, if you used `param2_data` and want to write it; - `light`: LVM buffer data array of light, !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - you load it yourself: - `vm_context.light = vm_context.light or vm_context.vm.get_light_data(vm_context.lvm_light_buffer)` - `write_light`: set it to true in your lvm callback function, if you used `light` and want to write it; - `lvm_param2_buffer`: static `param2` buffer pointer, used to load `param2_data` array; - `shadow`: set it to false to disable shadow propagation; - `heightmap`: mapgen object contanting y coordinates of ground level, - !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: - `vm_context.heightmap = vm_context.heightmap or minetest.get_mapgen_object('heightmap')` - `biomemap`: mapgen object contanting biome IDs of nodes, - !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: - `vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object('biomemap')` - `heatmap`: mapgen object contanting temperature values of nodes, - !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: - `vm_context.heatmap = vm_context.heatmap or minetest.get_mapgen_object('heatmap')` - `humiditymap`: mapgen object contanting humidity values of nodes, - !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: - `vm_context.humiditymap = vm_context.humiditymap or minetest.get_mapgen_object('humiditymap')` - `gennotify`: mapgen object contanting mapping table of structures, see Minetest Lua API for explanation, - !NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS! - load it yourself: - `vm_context.gennotify = vm_context.gennotify or minetest.get_mapgen_object('gennotify')` - `order_number` (optional): the less, the earlier, - e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` + + * `lvm_callback_function`: chunk callback LVM function definition: + * `function(vm_context)`: + * `vm_context` will pass into next lvm callback function from the queue! + * `vm_context`: a table which already contains some LVM data as the fields, and some of them can be added in your lvm callback function: + * `vm`: curent voxel manipulator object itself; + * `chunkseed`: seed of this mapchunk; + * `minp` & `maxp`: minimum and maximum chunk position; + * `emin` & `emax`: minimum and maximum chunk position WITH SHELL AROUND IT; + * `area`: voxel area, can be helpful to access data; + * `data`: LVM buffer data array, data loads into it before the callbacks; + * `write`: set it to true in your lvm callback functionm, if you changed `data` and want to write it; + * `param2_data`: LVM buffer data array of `param2`, *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - you load it yourself: + * `vm_context.param2_data = vm_context.param2_data or vm_context.vm:get_param2_data(vm_context.lvm_param2_buffer)` + * `write_param2`: set it to true in your lvm callback function, if you used `param2_data` and want to write it; + * `light`: LVM buffer data array of light, *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - you load it yourself: + * `vm_context.light = vm_context.light or vm_context.vm.get_light_data(vm_context.lvm_light_buffer)` + * `write_light`: set it to true in your lvm callback function, if you used `light` and want to write it; + * `lvm_param2_buffer`: static `param2` buffer pointer, used to load `param2_data` array; + * `shadow`: set it to false to disable shadow propagation; + * `heightmap`: mapgen object contanting y coordinates of ground level, + * *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself: + * `vm_context.heightmap = vm_context.heightmap or minetest.get_mapgen_object('heightmap')` + * `biomemap`: mapgen object contanting biome IDs of nodes, + * *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself: + * `vm_context.biomemap = vm_context.biomemap or minetest.get_mapgen_object('biomemap')` + * `heatmap`: mapgen object contanting temperature values of nodes, + * *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself: + * `vm_context.heatmap = vm_context.heatmap or minetest.get_mapgen_object('heatmap')` + * `humiditymap`: mapgen object contanting humidity values of nodes, + * *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself: + * `vm_context.humiditymap = vm_context.humiditymap or minetest.get_mapgen_object('humiditymap')` + * `gennotify`: mapgen object contanting mapping table of structures, see Minetest Lua API for explanation, + * *NO ANY DATA LOADS INTO IT BEFORE THE CALLBACKS* - load it yourself: + * `vm_context.gennotify = vm_context.gennotify or minetest.get_mapgen_object('gennotify')` + * `order_number` (optional): the less, the earlier, + * e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` ### mcl_mapgen.register_mapgen_block_lvm(lvm_callback_function, order_number) -============================================================================= +----------------------------------------------------------------------------- Registers lvm callback function to be called when current block (usually 16x16x16 nodes) generation is REALLY 100% finished. + `vm_context` passes into lvm callback function. - `lvm_callback_function`: the block callback LVM function definition - same as for chunks - see definition example above; - `order_number` (optional): the less, the earlier, - e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` + * `lvm_callback_function`: the block callback LVM function definition - same as for chunks - see definition example above; + * `order_number` (optional): the less, the earlier, + * e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` ### mcl_mapgen.register_mapgen_block(node_callback_function, order_number) -========================================================================== +-------------------------------------------------------------------------- Registers node_callback function to be called when current block (usually 16x16x16 nodes) generation is REALLY 100% finished. - `node_callback_function`: node callback function definition: - `function(minp, maxp, seed)`: - `minp` & `maxp`: minimum and maximum block position; - `seed`: seed of this mapblock; - `order_number` (optional): the less, the earlier, - e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` + * `node_callback_function`: node callback function definition: + * `function(minp, maxp, seed)`: + * `minp` & `maxp`: minimum and maximum block position; + * `seed`: seed of this mapblock; + * `order_number` (optional): the less, the earlier, + * e.g. `mcl_mapgen.order.BUILDINGS` or `mcl_mapgen.order.LARGE_BUILDINGS` ### mcl_mapgen.register_mapgen(callback_function, order_number) -==================================================================== +--------------------------------------------------------------- Registers callback function to be called when current chunk generation is REALLY 100% finished. + For LVM it's the most frustrating function from this mod. + It can't provide you access to mapgen objects. They are probably gone long ago. + Don't use it for accessing mapgen objects please. + To use VM you have to run `vm_context.vm = mcl_mapgen.get_voxel_manip(vm_context.emin, vm_context.emax)`. -Set - `callback_function`: callback function definition: - `function(minp, maxp, seed, vm_context)`: - `minp` & `maxp`: minimum and maximum block position; - `seed`: seed of this mapblock; - `vm_context`: a table - see description above. - `order_number` (optional): the less, the earlier. + * `callback_function`: callback function definition: + * `function(minp, maxp, seed, vm_context)`: + * `minp` & `maxp`: minimum and maximum block position; + * `seed`: seed of this mapblock; + * `vm_context`: a table - see description above. + * `order_number` (optional): the less, the earlier. ### mcl_mapgen.register_mapgen_lvm(lvm_callback_function, order_number) -======================================================================= +----------------------------------------------------------------------- Registers lvm callback function to be called when current chunk generation is REALLY 100% finished. + It's the most frustrating function from this mod. It can't provide you access to mapgen objects. They are probably gone long ago. + Don't use it for accessing mapgen objects please. + `vm_context` passes into lvm callback function. - `lvm_callback_function`: the block callback LVM function definition - same as above; - `order_number` (optional): the less, the earlier. + * `lvm_callback_function`: the block callback LVM function definition - same as above; + * `order_number` (optional): the less, the earlier. ### mcl_mapgen.get_far_node(pos) -================================ +-------------------------------- Returns node if it is generated, otherwise returns `{name = "ignore"}`. -## Constants: +### mcl_mapgen.clamp_to_chunk(x, size) +-------------------------------------- +Returns new `x`, slighty tuned to make structure of size `size` be within single chunk side of 80 nodes. -* `mcl_mapgen.EDGE_MIN`, `mcl_mapgen.EDGE_MAX` - world edges, min & max. -* `mcl_mapgen.seed`, `mcl_mapgen.name` - mapgen seed & name. -* `mcl_mapgen.v6`, `mcl_mapgen.superflat`, `mcl_mapgen.singlenode` - is mapgen v6, superflat, singlenode. -* `mcl_mapgen.normal` is mapgen normal (not superflat or singlenode). +### function mcl_mapgen.get_chunk_beginning(x) +---------------------------------------------- +Returns chunk beginning of `x`. It is the same as `minp.axis` for per-chunk callbacks, but we don't always have `minp`. + +## Constants: + * `mcl_mapgen.EDGE_MIN`, `mcl_mapgen.EDGE_MAX` - world edges, min & max. + * `mcl_mapgen.seed`, `mcl_mapgen.name` - mapgen seed & name. + * `mcl_mapgen.v6`, `mcl_mapgen.superflat`, `mcl_mapgen.singlenode` - is mapgen v6, superflat, singlenode. + * `mcl_mapgen.normal` is mapgen normal (not superflat or singlenode).