From ccb4b925ed168526182adcf06701e66e17125d84 Mon Sep 17 00:00:00 2001 From: paramat Date: Wed, 25 Mar 2015 23:30:27 +0000 Subject: [PATCH] default/mapgen.lua: Register mgv6 decorations Organise and cleanup code --- mods/default/mapgen.lua | 614 +++++++++++++++++++--------------------- 1 file changed, 292 insertions(+), 322 deletions(-) diff --git a/mods/default/mapgen.lua b/mods/default/mapgen.lua index a6cda35..9c177fd 100644 --- a/mods/default/mapgen.lua +++ b/mods/default/mapgen.lua @@ -1,9 +1,8 @@ --- mods/default/mapgen.lua - -- -- Aliases for map generator outputs -- + minetest.register_alias("mapgen_stone", "default:stone") minetest.register_alias("mapgen_tree", "default:tree") minetest.register_alias("mapgen_leaves", "default:leaves") @@ -27,11 +26,91 @@ minetest.register_alias("mapgen_desert_sand", "default:desert_sand") minetest.register_alias("mapgen_desert_stone", "default:desert_stone") minetest.register_alias("mapgen_stair_cobble", "stairs:stair_cobble") + -- -- Register ores -- + +-- Blob ore first to avoid other ores inside blobs + function default.register_ores() + minetest.register_ore({ + ore_type = "blob", + ore = "default:clay", + wherein = {"default:sand"}, + clust_scarcity = 24*24*24, + clust_size = 7, + y_min = -15, + y_max = 0, + noise_threshhold = 0, + noise_params = { + offset=0.35, + scale=0.2, + spread={x=5, y=5, z=5}, + seed=-316, + octaves=1, + persist=0.5 + }, + }) + + minetest.register_ore({ + ore_type = "blob", + ore = "default:sand", + wherein = {"default:stone"}, + clust_scarcity = 24*24*24, + clust_size = 7, + y_min = -63, + y_max = 4, + noise_threshhold = 0, + noise_params = { + offset=0.35, + scale=0.2, + spread={x=5, y=5, z=5}, + seed=2316, + octaves=1, + persist=0.5 + }, + }) + + minetest.register_ore({ + ore_type = "blob", + ore = "default:dirt", + wherein = {"default:stone"}, + clust_scarcity = 24*24*24, + clust_size = 7, + y_min = -63, + y_max = 31000, + noise_threshhold = 0, + noise_params = { + offset=0.35, + scale=0.2, + spread={x=5, y=5, z=5}, + seed=17676, + octaves=1, + persist=0.5 + }, + }) + + minetest.register_ore({ + ore_type = "blob", + ore = "default:gravel", + wherein = {"default:stone"}, + clust_scarcity = 24*24*24, + clust_size = 7, + y_min = -31000, + y_max = 31000, + noise_threshhold = 0, + noise_params = { + offset=0.35, + scale=0.2, + spread={x=5, y=5, z=5}, + seed=766, + octaves=1, + persist=0.5 + }, + }) + minetest.register_ore({ ore_type = "scatter", ore = "default:stone_with_coal", @@ -207,329 +286,14 @@ function default.register_ores() y_max = -64, flags = "absheight", }) - - minetest.register_ore({ - ore_type = "blob", - ore = "default:clay", - wherein = {"default:sand"}, - clust_scarcity = 24*24*24, - clust_size = 7, - y_min = -15, - y_max = 0, - noise_threshhold = 0, - noise_params = { - offset=0.35, - scale=0.2, - spread={x=5, y=5, z=5}, - seed=-316, - octaves=1, - persist=0.5 - }, - }) - - minetest.register_ore({ - ore_type = "blob", - ore = "default:sand", - wherein = {"default:stone"}, - clust_scarcity = 24*24*24, - clust_size = 7, - y_min = -63, - y_max = 4, - noise_threshhold = 0, - noise_params = { - offset=0.35, - scale=0.2, - spread={x=5, y=5, z=5}, - seed=2316, - octaves=1, - persist=0.5 - }, - }) - - minetest.register_ore({ - ore_type = "blob", - ore = "default:dirt", - wherein = {"default:stone"}, - clust_scarcity = 24*24*24, - clust_size = 7, - y_min = -63, - y_max = 31000, - noise_threshhold = 0, - noise_params = { - offset=0.35, - scale=0.2, - spread={x=5, y=5, z=5}, - seed=17676, - octaves=1, - persist=0.5 - }, - }) - - minetest.register_ore({ - ore_type = "blob", - ore = "default:gravel", - wherein = {"default:stone"}, - clust_scarcity = 24*24*24, - clust_size = 7, - y_min = -31000, - y_max = 31000, - noise_threshhold = 0, - noise_params = { - offset=0.35, - scale=0.2, - spread={x=5, y=5, z=5}, - seed=766, - octaves=1, - persist=0.5 - }, - }) end -function default.generate_ore(name, wherein, minp, maxp, seed, - chunks_per_volume, chunk_size, ore_per_chunk, height_min, height_max) - minetest.log('action', "WARNING: default.generate_ore is deprecated") - - if maxp.y < height_min or minp.y > height_max then - return - end - local y_min = math.max(minp.y, height_min) - local y_max = math.min(maxp.y, height_max) - if chunk_size >= y_max - y_min + 1 then - return - end - local volume = (maxp.x-minp.x+1)*(y_max-y_min+1)*(maxp.z-minp.z+1) - local pr = PseudoRandom(seed) - local num_chunks = math.floor(chunks_per_volume * volume) - local inverse_chance = math.floor(chunk_size*chunk_size*chunk_size / ore_per_chunk) - --print("generate_ore num_chunks: "..dump(num_chunks)) - for i=1,num_chunks do - local y0 = pr:next(y_min, y_max-chunk_size+1) - if y0 >= height_min and y0 <= height_max then - local x0 = pr:next(minp.x, maxp.x-chunk_size+1) - local z0 = pr:next(minp.z, maxp.z-chunk_size+1) - local p0 = {x=x0, y=y0, z=z0} - for x1=0,chunk_size-1 do - for y1=0,chunk_size-1 do - for z1=0,chunk_size-1 do - if pr:next(1,inverse_chance) == 1 then - local x2 = x0+x1 - local y2 = y0+y1 - local z2 = z0+z1 - local p2 = {x=x2, y=y2, z=z2} - if minetest.get_node(p2).name == wherein then - minetest.set_node(p2, {name=name}) - end - end - end - end - end - end - end - --print("generate_ore done") -end - --- --- Mgv6 papyrus, cactus, long grasses --- - -function default.mgv6_ongen(minp, maxp, seed) - function default.make_papyrus(pos, size) - for y=0,size-1 do - local p = {x=pos.x, y=pos.y+y, z=pos.z} - local nn = minetest.get_node(p).name - if minetest.registered_nodes[nn] and - minetest.registered_nodes[nn].buildable_to then - minetest.set_node(p, {name="default:papyrus"}) - else - return - end - end - end - - function default.make_cactus(pos, size) - for y=0,size-1 do - local p = {x=pos.x, y=pos.y+y, z=pos.z} - local nn = minetest.get_node(p).name - if minetest.registered_nodes[nn] and - minetest.registered_nodes[nn].buildable_to then - minetest.set_node(p, {name="default:cactus"}) - else - return - end - end - end - - if maxp.y >= 2 and minp.y <= 0 then - -- Generate papyrus - local perlin1 = minetest.get_perlin(354, 3, 0.7, 100) - -- Assume X and Z lengths are equal - local divlen = 8 - local divs = (maxp.x-minp.x)/divlen+1; - for divx=0,divs-1 do - for divz=0,divs-1 do - local x0 = minp.x + math.floor((divx+0)*divlen) - local z0 = minp.z + math.floor((divz+0)*divlen) - local x1 = minp.x + math.floor((divx+1)*divlen) - local z1 = minp.z + math.floor((divz+1)*divlen) - -- Determine papyrus amount from perlin noise - local papyrus_amount = math.floor(perlin1:get2d({x=x0, y=z0}) * 45 - 20) - -- Find random positions for papyrus based on this random - local pr = PseudoRandom(seed+1) - for i=0,papyrus_amount do - local x = pr:next(x0, x1) - local z = pr:next(z0, z1) - if minetest.get_node({x=x,y=1,z=z}).name == "default:dirt_with_grass" and - minetest.find_node_near({x=x,y=1,z=z}, 1, "default:water_source") then - default.make_papyrus({x=x,y=2,z=z}, pr:next(2, 4)) - end - end - end - end - -- Generate cactuses - local perlin1 = minetest.get_perlin(230, 3, 0.6, 100) - -- Assume X and Z lengths are equal - local divlen = 16 - local divs = (maxp.x-minp.x)/divlen+1; - for divx=0,divs-1 do - for divz=0,divs-1 do - local x0 = minp.x + math.floor((divx+0)*divlen) - local z0 = minp.z + math.floor((divz+0)*divlen) - local x1 = minp.x + math.floor((divx+1)*divlen) - local z1 = minp.z + math.floor((divz+1)*divlen) - -- Determine cactus amount from perlin noise - local cactus_amount = math.floor(perlin1:get2d({x=x0, y=z0}) * 6 - 3) - -- Find random positions for cactus based on this random - local pr = PseudoRandom(seed+1) - for i=0,cactus_amount do - local x = pr:next(x0, x1) - local z = pr:next(z0, z1) - -- Find ground level (0...15) - local ground_y = nil - for y=30,0,-1 do - if minetest.get_node({x=x,y=y,z=z}).name ~= "air" then - ground_y = y - break - end - end - -- If desert sand, make cactus - if ground_y and minetest.get_node({x=x,y=ground_y,z=z}).name == "default:desert_sand" then - default.make_cactus({x=x,y=ground_y+1,z=z}, pr:next(3, 4)) - end - end - end - end - -- Generate grass - local perlin1 = minetest.get_perlin(329, 3, 0.6, 100) - -- Assume X and Z lengths are equal - local divlen = 16 - local divs = (maxp.x-minp.x)/divlen+1; - for divx=0,divs-1 do - for divz=0,divs-1 do - local x0 = minp.x + math.floor((divx+0)*divlen) - local z0 = minp.z + math.floor((divz+0)*divlen) - local x1 = minp.x + math.floor((divx+1)*divlen) - local z1 = minp.z + math.floor((divz+1)*divlen) - -- Determine grass amount from perlin noise - local grass_amount = math.floor(perlin1:get2d({x=x0, y=z0}) ^ 3 * 9) - -- Find random positions for grass based on this random - local pr = PseudoRandom(seed+1) - for i=0,grass_amount do - local x = pr:next(x0, x1) - local z = pr:next(z0, z1) - -- Find ground level (0...15) - local ground_y = nil - for y=30,0,-1 do - if minetest.get_node({x=x,y=y,z=z}).name ~= "air" then - ground_y = y - break - end - end - - if ground_y then - local p = {x=x,y=ground_y+1,z=z} - local nn = minetest.get_node(p).name - -- Check if the node can be replaced - if minetest.registered_nodes[nn] and - minetest.registered_nodes[nn].buildable_to then - nn = minetest.get_node({x=x,y=ground_y,z=z}).name - -- If desert sand, add dry shrub - if nn == "default:desert_sand" then - minetest.set_node(p,{name="default:dry_shrub"}) - - -- If dirt with grass, add grass - elseif nn == "default:dirt_with_grass" then - minetest.set_node(p,{name="default:grass_"..pr:next(1, 5)}) - end - end - end - - end - end - end - end -end - --- --- Generate nyan cats in all mapgens --- - --- facedir: 0/1/2/3 (head node facedir value) --- length: length of rainbow tail -function default.make_nyancat(pos, facedir, length) - local tailvec = {x=0, y=0, z=0} - if facedir == 0 then - tailvec.z = 1 - elseif facedir == 1 then - tailvec.x = 1 - elseif facedir == 2 then - tailvec.z = -1 - elseif facedir == 3 then - tailvec.x = -1 - else - --print("default.make_nyancat(): Invalid facedir: "+dump(facedir)) - facedir = 0 - tailvec.z = 1 - end - local p = {x=pos.x, y=pos.y, z=pos.z} - minetest.set_node(p, {name="default:nyancat", param2=facedir}) - for i=1,length do - p.x = p.x + tailvec.x - p.z = p.z + tailvec.z - minetest.set_node(p, {name="default:nyancat_rainbow", param2=facedir}) - end -end - - -function default.generate_nyancats(minp, maxp, seed) - local height_min = -31000 - local height_max = -32 - if maxp.y < height_min or minp.y > height_max then - return - end - local y_min = math.max(minp.y, height_min) - local y_max = math.min(maxp.y, height_max) - local volume = (maxp.x-minp.x+1)*(y_max-y_min+1)*(maxp.z-minp.z+1) - local pr = PseudoRandom(seed + 9324342) - local max_num_nyancats = math.floor(volume / (16*16*16)) - for i=1,max_num_nyancats do - if pr:next(0, 1000) == 0 then - local x0 = pr:next(minp.x, maxp.x) - local y0 = pr:next(minp.y, maxp.y) - local z0 = pr:next(minp.z, maxp.z) - local p0 = {x=x0, y=y0, z=z0} - default.make_nyancat(p0, pr:next(0,3), pr:next(3,15)) - end - end -end - - -minetest.register_on_generated(default.generate_nyancats) - -- -- Register biomes -- + function default.register_biomes() minetest.clear_registered_biomes() @@ -567,11 +331,105 @@ function default.register_biomes() humidity_point = 50, }) end - + + +-- +-- Register mgv6 decorations +-- + + +function default.register_mgv6_decorations() + + -- Papyrus + + minetest.register_decoration({ + deco_type = "simple", + place_on = {"default:dirt_with_grass"}, + sidelen = 8, + noise_params = { + offset = -0.3, + scale = 0.7, + spread = {x=100, y=100, z=100}, + seed = 354, + octaves = 3, + persist = 0.7 + }, + y_min = 1, + y_max = 1, + decoration = "default:papyrus", + height = 2, + height_max = 4, + spawn_by = "default:water_source", + }) + + -- Cacti + + minetest.register_decoration({ + deco_type = "simple", + place_on = {"default:desert_sand"}, + sidelen = 16, + noise_params = { + offset = -0.012, + scale = 0.024, + spread = {x=100, y=100, z=100}, + seed = 230, + octaves = 3, + persist = 0.6 + }, + y_min = 1, + y_max = 30, + decoration = "default:cactus", + height = 3, + height_max = 4, + }) + + -- Grasses + + for length = 1, 5 do + minetest.register_decoration({ + deco_type = "simple", + place_on = {"default:dirt_with_grass"}, + sidelen = 16, + noise_params = { + offset = 0, + scale = 0.007, + spread = {x=100, y=100, z=100}, + seed = 329, + octaves = 3, + persist = 0.6 + }, + y_min = 1, + y_max = 30, + decoration = "default:grass_"..length, + }) + end + + -- Dry shrubs + + minetest.register_decoration({ + deco_type = "simple", + place_on = {"default:desert_sand"}, + sidelen = 16, + noise_params = { + offset = 0, + scale = 0.035, + spread = {x=100, y=100, z=100}, + seed = 329, + octaves = 3, + persist = 0.6 + }, + y_min = 1, + y_max = 30, + decoration = "default:dry_shrub", + }) +end + + -- -- Register decorations -- + function default.register_decorations() -- Flowers @@ -777,21 +635,133 @@ function default.register_decorations() }) end + -- -- Detect mapgen to select functions -- + +-- Mods using singlenode mapgen can call these functions to enable +-- the use of minetest.generate_ores or minetest.generate_decorations + local mg_params = minetest.get_mapgen_params() if mg_params.mgname == "v5" then + default.register_ores() default.register_biomes() default.register_decorations() - default.register_ores() elseif mg_params.mgname == "v6" then - minetest.register_on_generated(default.mgv6_ongen) default.register_ores() + default.register_mgv6_decorations() elseif mg_params.mgname == "v7" then + default.register_ores() default.register_biomes() default.register_decorations() - default.register_ores() +end + + +-- +-- Generate nyan cats in all mapgens +-- + + +-- facedir: 0/1/2/3 (head node facedir value) +-- length: length of rainbow tail +function default.make_nyancat(pos, facedir, length) + local tailvec = {x=0, y=0, z=0} + if facedir == 0 then + tailvec.z = 1 + elseif facedir == 1 then + tailvec.x = 1 + elseif facedir == 2 then + tailvec.z = -1 + elseif facedir == 3 then + tailvec.x = -1 + else + --print("default.make_nyancat(): Invalid facedir: "+dump(facedir)) + facedir = 0 + tailvec.z = 1 + end + local p = {x=pos.x, y=pos.y, z=pos.z} + minetest.set_node(p, {name="default:nyancat", param2=facedir}) + for i=1,length do + p.x = p.x + tailvec.x + p.z = p.z + tailvec.z + minetest.set_node(p, {name="default:nyancat_rainbow", param2=facedir}) + end +end + + +function default.generate_nyancats(minp, maxp, seed) + local height_min = -31000 + local height_max = -32 + if maxp.y < height_min or minp.y > height_max then + return + end + local y_min = math.max(minp.y, height_min) + local y_max = math.min(maxp.y, height_max) + local volume = (maxp.x-minp.x+1)*(y_max-y_min+1)*(maxp.z-minp.z+1) + local pr = PseudoRandom(seed + 9324342) + local max_num_nyancats = math.floor(volume / (16*16*16)) + for i=1,max_num_nyancats do + if pr:next(0, 1000) == 0 then + local x0 = pr:next(minp.x, maxp.x) + local y0 = pr:next(minp.y, maxp.y) + local z0 = pr:next(minp.z, maxp.z) + local p0 = {x=x0, y=y0, z=z0} + default.make_nyancat(p0, pr:next(0,3), pr:next(3,15)) + end + end +end + + +minetest.register_on_generated(default.generate_nyancats) + + +-- +-- Deprecated ore generation code +-- + + +function default.generate_ore(name, wherein, minp, maxp, seed, + chunks_per_volume, chunk_size, ore_per_chunk, height_min, height_max) + minetest.log('action', "WARNING: default.generate_ore is deprecated") + + if maxp.y < height_min or minp.y > height_max then + return + end + local y_min = math.max(minp.y, height_min) + local y_max = math.min(maxp.y, height_max) + if chunk_size >= y_max - y_min + 1 then + return + end + local volume = (maxp.x-minp.x+1)*(y_max-y_min+1)*(maxp.z-minp.z+1) + local pr = PseudoRandom(seed) + local num_chunks = math.floor(chunks_per_volume * volume) + local inverse_chance = math.floor(chunk_size*chunk_size*chunk_size / ore_per_chunk) + --print("generate_ore num_chunks: "..dump(num_chunks)) + for i=1,num_chunks do + local y0 = pr:next(y_min, y_max-chunk_size+1) + if y0 >= height_min and y0 <= height_max then + local x0 = pr:next(minp.x, maxp.x-chunk_size+1) + local z0 = pr:next(minp.z, maxp.z-chunk_size+1) + local p0 = {x=x0, y=y0, z=z0} + for x1=0,chunk_size-1 do + for y1=0,chunk_size-1 do + for z1=0,chunk_size-1 do + if pr:next(1,inverse_chance) == 1 then + local x2 = x0+x1 + local y2 = y0+y1 + local z2 = z0+z1 + local p2 = {x=x2, y=y2, z=z2} + if minetest.get_node(p2).name == wherein then + minetest.set_node(p2, {name=name}) + end + end + end + end + end + end + end + --print("generate_ore done") end