From 212e7d000e51912aa2ae0fade6820335a607c659 Mon Sep 17 00:00:00 2001 From: Splizard Date: Fri, 9 Aug 2013 00:37:05 +0000 Subject: [PATCH] Add voxelmanip support for dev minetest and smooth ice mapgen_v6 --- mapgen.lua | 65 +++++ mapgen_v6.lua | 694 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 555 insertions(+), 204 deletions(-) diff --git a/mapgen.lua b/mapgen.lua index 582acf0..7f4afd1 100644 --- a/mapgen.lua +++ b/mapgen.lua @@ -91,3 +91,68 @@ function snow.make_pine(pos,snow,xmas) try_node({x=pos.x,y=pos.y+7,z=pos.z},{name="snow:snow"}) end end + +--Makes pine tree +function snow.voxelmanip_pine(pos,a,data) + local c_snow = minetest.get_content_id("snow:snow") + local c_pine_needles = minetest.get_content_id("snow:needles") + local c_tree = minetest.get_content_id("default:tree") + local c_air = minetest.get_content_id("air") + + local perlin1 = minetest.get_perlin(112,3, 0.5, 150) + --Clear ground. + for x=-1,1 do + for z=-1,1 do + local node = a:index(pos.x+x,pos.y,pos.z+z) + if data[node] == c_snow then + data[node] = c_air + end + end + end + --Make tree. + for i=0, 4 do + if i==1 or i==2 then + for x=-1,1 do + for z=-1,1 do + local x = pos.x + x + local z = pos.z + z + local node = a:index(x,pos.y+i,z) + data[node] = c_pine_needles + if snow and x ~= 0 and z ~= 0 and perlin1:get2d({x=x,y=z}) > 0.53 then + local abovenode = a:index(x,pos.y+i+1,z) + data[abovenode] = c_snow + end + end + end + end + if i==3 or i==4 then + local x = pos.x + local y = pos.y+i + local z = pos.z + data[a:index(x+1,y,z)] = c_pine_needles + data[a:index(x-1,y,z)] = c_pine_needles + data[a:index(x,y,z+1)] = c_pine_needles + data[a:index(x,y,z-1)] = c_pine_needles + if snow then + if perlin1:get2d({x=x+1,y=z}) > 0.53 then + data[a:index(x+1,y+1,z)] = c_snow + end + if perlin1:get2d({x=x+1,y=z}) > 0.53 then + data[a:index(x-1,y+1,z)] = c_snow + end + if perlin1:get2d({x=x,y=z+1}) > 0.53 then + data[a:index(x,y+1,z+1)] = c_snow + end + if perlin1:get2d({x=x,y=z-1}) > 0.53 then + data[a:index(x,y+1,z-1)] = c_snow + end + end + end + data[a:index(pos.x,pos.y+i,pos.z)] = c_tree + end + data[a:index(pos.x,pos.y+5,pos.z)] = c_pine_needles + data[a:index(pos.x,pos.y+6,pos.z)] = c_pine_needles + if snow and perlin1:get2d({x=pos.x,y=pos.z}) > 0.53 then + data[a:index(pos.x,pos.y+7,pos.z)] = c_snow + end +end diff --git a/mapgen_v6.lua b/mapgen_v6.lua index eb7acde..8fc0c01 100644 --- a/mapgen_v6.lua +++ b/mapgen_v6.lua @@ -1,234 +1,520 @@ ---Snow biomes are found at 0.53 and greater perlin noise. -minetest.register_on_generated(function(minp, maxp, seed) - if maxp.y >= -10 and maxp.y > snow.min_height then - local debug = snow.debug - local min_height = snow.min_height +if snow.legacy then + --Snow biomes are found at 0.53 and greater perlin noise. + minetest.register_on_generated(function(minp, maxp, seed) + if maxp.y >= -10 and maxp.y > snow.min_height then + local debug = snow.debug + local min_height = snow.min_height + + --Should make things a bit faster. + local env = minetest.env - --Should make things a bit faster. - local env = minetest.env + --Get map specific perlin + local perlin1 = env:get_perlin(112,3, 0.5, 150) - --Get map specific perlin - local perlin1 = env:get_perlin(112,3, 0.5, 150) + -- Assume X and Z lengths are equal + local divlen = 16 + local divs = (maxp.x-minp.x); + local x0 = minp.x + local z0 = minp.z + local x1 = maxp.x + local z1 = maxp.z - -- Assume X and Z lengths are equal - local divlen = 16 - local divs = (maxp.x-minp.x); - local x0 = minp.x - local z0 = minp.z - local x1 = maxp.x - local z1 = maxp.z - - --Speed hack: checks the corners and middle of the chunk for "snow biome". - if not ( perlin1:get2d( {x=x0, y=z0} ) > 0.53 ) --top left - and not ( perlin1:get2d( { x = x0 + ( (x1-x0)/2), y=z0 } ) > 0.53 )--top middle - and not (perlin1:get2d({x=x1, y=z1}) > 0.53) --bottom right - and not (perlin1:get2d({x=x1, y=z0+((z1-z0)/2)}) > 0.53) --right middle - and not (perlin1:get2d({x=x0, y=z1}) > 0.53) --bottom left - and not (perlin1:get2d({x=x1, y=z0}) > 0.53) --top right - and not (perlin1:get2d({x=x0+((x1-x0)/2), y=z1}) > 0.53) --left middle - and not (perlin1:get2d({x=(x1-x0)/2, y=(z1-z0)/2}) > 0.53) --middle - and not (perlin1:get2d({x=x0, y=z1+((z1-z0)/2)}) > 0.53) then --bottom middle - return - end - - --Choose a biome types. - local pr = PseudoRandom(seed+57) - local biome - - --Land biomes - biome = pr:next(1, 5) - local snowy = biome == 1 --spawns alot of snow - local plain = biome == 2 --spawns not much - local alpine = biome == 3 --rocky terrain - -- biome == 4 or biome == 5 -- normal biome - - --Water biomes - biome2 = pr:next(1, 5) - local cool = biome == 1 --only spawns ice on edge of water - local icebergs = biome == 2 - local icesheet = biome == 3 - local icecave = biome == 4 - local icehole = biome == 5 --icesheet with holes - - --Misc biome settings. - local icy = pr:next(1, 2) == 2 --If enabled spawns ice in sand instead of snow blocks. - local mossy = pr:next(1,2) == 1 --Spawns moss in snow. - local shrubs = pr:next(1,2) == 1 --Spawns dry shrubs in snow. - local pines = pr:next(1,2) == 1 --spawns pines. - - --Debugging function - local biomeToString = function(num,num2) - local biome, biome2 - if num == 1 then biome = "snowy" - elseif num == 2 then biome = "plain" - elseif num == 3 then biome = "alpine" - elseif num == 4 or num == 5 then biome = "normal" - else biome = "unknown "..num end - - if num2 == 1 then biome2 = "cool" - elseif num2 == 2 then biome2 = "icebergs" - elseif num2 == 3 then biome2 = "icesheet" - elseif num2 == 4 then biome2 = "icecave" - elseif num2 == 5 then biome2 = "icehole" - else biome2 = "unknown "..num end - - return biome, biome2 - end - - local make_pine = snow.make_pine - local smooth = snow.smooth_biomes - local legacy = snow.legacy - - --Reseed random. - pr = PseudoRandom(seed+68) - - if alpine then - local trees = env:find_nodes_in_area(minp, maxp, {"default:leaves","default:tree"}) - for i,v in pairs(trees) do - env:remove_node(v) + --Speed hack: checks the corners and middle of the chunk for "snow biome". + if not ( perlin1:get2d( {x=x0, y=z0} ) > 0.53 ) --top left + and not ( perlin1:get2d( { x = x0 + ( (x1-x0)/2), y=z0 } ) > 0.53 )--top middle + and not (perlin1:get2d({x=x1, y=z1}) > 0.53) --bottom right + and not (perlin1:get2d({x=x1, y=z0+((z1-z0)/2)}) > 0.53) --right middle + and not (perlin1:get2d({x=x0, y=z1}) > 0.53) --bottom left + and not (perlin1:get2d({x=x1, y=z0}) > 0.53) --top right + and not (perlin1:get2d({x=x0+((x1-x0)/2), y=z1}) > 0.53) --left middle + and not (perlin1:get2d({x=(x1-x0)/2, y=(z1-z0)/2}) > 0.53) --middle + and not (perlin1:get2d({x=x0, y=z1+((z1-z0)/2)}) > 0.53) then --bottom middle + return end - end - --Loop through chunk. - for j=0,divs do - for i=0,divs do + --Choose a biome types. + local pr = PseudoRandom(seed+57) + local biome - local x = x0+i - local z = z0+j + --Land biomes + biome = pr:next(1, 5) + local snowy = biome == 1 --spawns alot of snow + local plain = biome == 2 --spawns not much + local alpine = biome == 3 --rocky terrain + -- biome == 4 or biome == 5 -- normal biome - --Check if we are in a "Snow biome" - local in_biome = false - local test = perlin1:get2d({x=x, y=z}) - if smooth and (not snowy) and (test > 0.73 or (test > 0.43 and pr:next(0,29) > (0.73 - test) * 100 )) then - in_biome = true - elseif (not smooth or snowy) and test > 0.53 then - in_biome = true - end + --Water biomes + biome2 = pr:next(1, 5) + local cool = biome == 1 --only spawns ice on edge of water + local icebergs = biome == 2 + local icesheet = biome == 3 + local icecave = biome == 4 + local icehole = biome == 5 --icesheet with holes - if in_biome then + --Misc biome settings. + local icy = pr:next(1, 2) == 2 --If enabled spawns ice in sand instead of snow blocks. + local mossy = pr:next(1,2) == 1 --Spawns moss in snow. + local shrubs = pr:next(1,2) == 1 --Spawns dry shrubs in snow. + local pines = pr:next(1,2) == 1 --spawns pines. - if not plain or pr:next(1,12) == 1 then + --Debugging function + local biomeToString = function(num,num2) + local biome, biome2 + if num == 1 then biome = "snowy" + elseif num == 2 then biome = "plain" + elseif num == 3 then biome = "alpine" + elseif num == 4 or num == 5 then biome = "normal" + else biome = "unknown "..num end - -- Find ground level (0...15) - local ground_y = nil - for y=maxp.y,minp.y+1,-1 do - if env:get_node({x=x,y=y,z=z}).name ~= "air" then - ground_y = y - break + if num2 == 1 then biome2 = "cool" + elseif num2 == 2 then biome2 = "icebergs" + elseif num2 == 3 then biome2 = "icesheet" + elseif num2 == 4 then biome2 = "icecave" + elseif num2 == 5 then biome2 = "icehole" + else biome2 = "unknown "..num end + + return biome, biome2 + end + + local make_pine = snow.make_pine + local smooth = snow.smooth_biomes + local legacy = snow.legacy + + --Reseed random. + pr = PseudoRandom(seed+68) + + if alpine then + local trees = env:find_nodes_in_area(minp, maxp, {"default:leaves","default:tree"}) + for i,v in pairs(trees) do + env:remove_node(v) + end + end + + --Loop through chunk. + for j=0,divs do + for i=0,divs do + + local x = x0+i + local z = z0+j + + --Check if we are in a "Snow biome" + local in_biome = false + local test = perlin1:get2d({x=x+150, y=z+50}) + if smooth and (not snowy) and (test < -0.73 or (test < -0.43 and pr:next(0,29) < (-0.73 + test) * 100 )) then + in_biome = true + elseif (not smooth or snowy) and test < -0.53 then + in_biome = true + end + + if in_biome then + + if not plain or pr:next(1,12) == 1 then + + -- Find ground level (0...15) + local ground_y = nil + for y=maxp.y,minp.y+1,-1 do + if env:get_node({x=x,y=y,z=z}).name ~= "air" then + ground_y = y + break + end end - end - if ground_y and ground_y > min_height then + if ground_y and ground_y > min_height then - -- Snowy biome stuff - local node = env:get_node({x=x,y=ground_y,z=z}) + -- Snowy biome stuff + local node = env:get_node({x=x,y=ground_y,z=z}) - if ground_y and (node.name == "default:dirt_with_grass" or node.name == "default:junglegrass") then - local veg - if legacy and mossy and pr:next(1,10) == 1 then veg = 1 end - if alpine then - --Gets rid of dirt - env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow", param2=veg}) - for y=ground_y,-6,-1 do - if env:get_node({x=x,y=y,z=z}) and env:get_node({x=x,y=y,z=z}).name == "default:stone" then - break - else - env:add_node({x=x,y=y,z=z},{name="default:stone"}) + if ground_y and (node.name == "default:dirt_with_grass" or node.name == "default:junglegrass") then + local veg + if legacy and mossy and pr:next(1,10) == 1 then veg = 1 end + if alpine then + --Gets rid of dirt + env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow", param2=veg}) + for y=ground_y,-6,-1 do + if env:get_node({x=x,y=y,z=z}) and env:get_node({x=x,y=y,z=z}).name == "default:stone" then + break + else + env:add_node({x=x,y=y,z=z},{name="default:stone"}) + end end - end - elseif (shrubs and pr:next(1,28) == 1) or node.name == "default:junglegrass" then - --Spawns dry shrubs. - env:add_node({x=x,y=ground_y,z=z}, {name="snow:dirt_with_snow"}) - if snowy then + elseif (shrubs and pr:next(1,28) == 1) or node.name == "default:junglegrass" then + --Spawns dry shrubs. + env:add_node({x=x,y=ground_y,z=z}, {name="snow:dirt_with_snow"}) + if snowy then + env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow_block"}) + else + env:add_node({x=x,y=ground_y+1,z=z}, {name="default:dry_shrub"}) + end + elseif pines and pr:next(1,36) == 1 then + --Spawns pines. + env:add_node({x=x,y=ground_y,z=z}, {name="default:dirt_with_grass"}) + make_pine({x=x,y=ground_y+1,z=z},true) + elseif snowy then + --Spawns snow blocks. env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow_block"}) + env:add_node({x=x,y=ground_y+2,z=z}, {name="snow:snow", param2=veg}) else - env:add_node({x=x,y=ground_y+1,z=z}, {name="default:dry_shrub"}) + --Spawns snow. + env:add_node({x=x,y=ground_y,z=z}, {name="snow:dirt_with_snow"}) + env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow", param2=veg}) end - elseif pines and pr:next(1,36) == 1 then - --Spawns pines. - env:add_node({x=x,y=ground_y,z=z}, {name="default:dirt_with_grass"}) - make_pine({x=x,y=ground_y+1,z=z},true) - elseif snowy then - --Spawns snow blocks. - env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow_block"}) - env:add_node({x=x,y=ground_y+2,z=z}, {name="snow:snow", param2=veg}) - else - --Spawns snow. - env:add_node({x=x,y=ground_y,z=z}, {name="snow:dirt_with_snow"}) - env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow", param2=veg}) - end - elseif ground_y and node.name == "default:sand" then - --Spawns ice in sand if icy, otherwise spawns snow on top. - if not icy then - env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow"}) - env:add_node({x=x,y=ground_y,z=z}, {name="snow:snow_block"}) - else - env:add_node({x=x,y=ground_y,z=z}, {name="snow:ice"}) - end - elseif ground_y and env:get_node({x=x,y=ground_y,z=z}).name == "default:leaves" then - env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow"}) - elseif ground_y and env:get_node({x=x,y=ground_y,z=z}).name == "default:papyrus" then - for i=ground_y, ground_y-4, -1 do - if env:get_node({x=x,y=i,z=z}).name == "default:papyrus" then + elseif ground_y and node.name == "default:sand" then + --Spawns ice in sand if icy, otherwise spawns snow on top. + if not icy then env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow"}) - env:add_node({x=x,y=i,z=z}, {name="snow:snow_block", param2=2}) - end - end - elseif ground_y and node.name == "default:water_source" then - if not icesheet and not icecave and not icehole then - --Coastal ice. - local x1 = env:get_node({x=x+1,y=ground_y,z=z}).name - local z1 = env:get_node({x=x,y=ground_y,z=z+1}).name - local xz1 = env:get_node({x=x+1,y=ground_y,z=z+1}).name - local xz2 = env:get_node({x=x-1,y=ground_y,z=z-1}).name - local x2 = env:get_node({x=x-1,y=ground_y,z=z}).name - local z2 = env:get_node({x=x,y=ground_y,z=z-1}).name - local y = env:get_node({x=x,y=ground_y-1,z=z}).name - local rand = pr:next(1,4) == 1 - if - ((x1 and x1 ~= "default:water_source" and x1 ~= "snow:ice" and x1 ~= "air" and x1 ~= "ignore") or ((cool or icebergs) and x1 == "snow:ice" and rand)) or - ((z1 and z1 ~= "default:water_source" and z1 ~= "snow:ice" and z1 ~= "air" and z1 ~= "ignore") or ((cool or icebergs) and z1 == "snow:ice" and rand)) or - ((xz1 and xz1 ~= "default:water_source" and xz1 ~= "snow:ice" and xz1 ~= "air"and xz1 ~= "ignore") or ((cool or icebergs) and xz1 == "snow:ice" and rand)) or - ((xz2 and xz2 ~= "default:water_source" and xz2 ~= "snow:ice" and xz2 ~= "air"and xz2 ~= "ignore") or ((cool or icebergs) and xz2 == "snow:ice" and rand)) or - ((x2 and x2 ~= "default:water_source" and x2 ~= "snow:ice" and x2 ~= "air" and x2 ~= "ignore") or ((cool or icebergs) and x2 == "snow:ice" and rand)) or - ((z2 and z2 ~= "default:water_source" and z2 ~= "snow:ice" and z2 ~= "air" and z2 ~= "ignore") or ((cool or icebergs) and z2 == "snow:ice" and rand)) or - (y ~= "default:water_source" and y ~= "snow:ice" and y ~= "air") or (pr:next(1,6) == 1 and icebergs) then - env:add_node({x=x,y=ground_y,z=z}, {name="snow:ice"}) - end - else - --Icesheets, Broken icesheet, Icecaves - if (icehole and pr:next(1,10) > 1) or icecave or icesheet then + env:add_node({x=x,y=ground_y,z=z}, {name="snow:snow_block"}) + else env:add_node({x=x,y=ground_y,z=z}, {name="snow:ice"}) end - if icecave then - --Gets rid of water underneath ice - for y=ground_y-1,-60,-1 do - if env:get_node({x=x,y=y,z=z}) and env:get_node({x=x,y=y,z=z}).name ~= "default:water_source" then - break - else - env:remove_node({x=x,y=y,z=z}) + elseif ground_y and env:get_node({x=x,y=ground_y,z=z}).name == "default:leaves" then + env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow"}) + elseif ground_y and env:get_node({x=x,y=ground_y,z=z}).name == "default:papyrus" then + for i=ground_y, ground_y-4, -1 do + if env:get_node({x=x,y=i,z=z}).name == "default:papyrus" then + env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow"}) + env:add_node({x=x,y=i,z=z}, {name="snow:snow_block", param2=2}) + end + end + elseif ground_y and node.name == "default:water_source" then + if not icesheet and not icecave and not icehole then + --Coastal ice. + local x1 = env:get_node({x=x+1,y=ground_y,z=z}).name + local z1 = env:get_node({x=x,y=ground_y,z=z+1}).name + local xz1 = env:get_node({x=x+1,y=ground_y,z=z+1}).name + local xz2 = env:get_node({x=x-1,y=ground_y,z=z-1}).name + local x2 = env:get_node({x=x-1,y=ground_y,z=z}).name + local z2 = env:get_node({x=x,y=ground_y,z=z-1}).name + local y = env:get_node({x=x,y=ground_y-1,z=z}).name + local rand = pr:next(1,4) == 1 + if + ((x1 and x1 ~= "default:water_source" and x1 ~= "snow:ice" and x1 ~= "air" and x1 ~= "ignore") or ((cool or icebergs) and x1 == "snow:ice" and rand)) or + ((z1 and z1 ~= "default:water_source" and z1 ~= "snow:ice" and z1 ~= "air" and z1 ~= "ignore") or ((cool or icebergs) and z1 == "snow:ice" and rand)) or + ((xz1 and xz1 ~= "default:water_source" and xz1 ~= "snow:ice" and xz1 ~= "air"and xz1 ~= "ignore") or ((cool or icebergs) and xz1 == "snow:ice" and rand)) or + ((xz2 and xz2 ~= "default:water_source" and xz2 ~= "snow:ice" and xz2 ~= "air"and xz2 ~= "ignore") or ((cool or icebergs) and xz2 == "snow:ice" and rand)) or + ((x2 and x2 ~= "default:water_source" and x2 ~= "snow:ice" and x2 ~= "air" and x2 ~= "ignore") or ((cool or icebergs) and x2 == "snow:ice" and rand)) or + ((z2 and z2 ~= "default:water_source" and z2 ~= "snow:ice" and z2 ~= "air" and z2 ~= "ignore") or ((cool or icebergs) and z2 == "snow:ice" and rand)) or + (y ~= "default:water_source" and y ~= "snow:ice" and y ~= "air") or (pr:next(1,6) == 1 and icebergs) then + env:add_node({x=x,y=ground_y,z=z}, {name="snow:ice"}) + end + else + --Icesheets, Broken icesheet, Icecaves + if (icehole and pr:next(1,10) > 1) or icecave or icesheet then + env:add_node({x=x,y=ground_y,z=z}, {name="snow:ice"}) + end + if icecave then + --Gets rid of water underneath ice + for y=ground_y-1,-60,-1 do + if env:get_node({x=x,y=y,z=z}) and env:get_node({x=x,y=y,z=z}).name ~= "default:water_source" then + break + else + env:remove_node({x=x,y=y,z=z}) + end end end end - end - --~ elseif ground_y and node.name == "snow:snow" and node.name ~= "snow:ice" then - --~ --Abort genaration. - --~ local name = env:get_node({x=x,y=ground_y-1,z=z}).name - --~ if name ~= "default:leaves" and name ~= "snow:needles" then - --~ if debug then - --~ print(biomeToString(biome)..": snow found ABORTED!") + --~ elseif ground_y and node.name == "snow:snow" and node.name ~= "snow:ice" then + --~ --Abort genaration. + --~ local name = env:get_node({x=x,y=ground_y-1,z=z}).name + --~ if name ~= "default:leaves" and name ~= "snow:needles" then + --~ if debug then + --~ print(biomeToString(biome)..": snow found ABORTED!") + --~ end + --~ return --~ end - --~ return - --~ end + end end end end end + end + if debug then + biome_string,biome2_string = biomeToString(biome,biome2) + print(biome_string.." and "..biome2_string..": Snow Biome Genarated near x"..minp.x.." z"..minp.z) + end end - end - if debug then - biome_string,biome2_string = biomeToString(biome,biome2) - print(biome_string.." and "..biome2_string..": Snow Biome Genarated near x"..minp.x.." z"..minp.z) - end - end -end) + end) +else + + --Identify content ID's of nodes + local c_dirt_with_grass = minetest.get_content_id("default:dirt_with_grass") + local c_snow = minetest.get_content_id("snow:snow") + local c_snow_block = minetest.get_content_id("snow:snow_block") + local c_dirt_with_snow = minetest.get_content_id("snow:dirt_with_snow") + local c_air = minetest.get_content_id("air") + local c_ignore = minetest.get_content_id("ignore") + local c_stone = minetest.get_content_id("default:stone") + local c_dry_shrub = minetest.get_content_id("default:dry_shrub") + local c_leaves = minetest.get_content_id("default:leaves") + local c_ice = minetest.get_content_id("snow:ice") + local c_water = minetest.get_content_id("default:water_source") + local c_papyrus = minetest.get_content_id("default:papyrus") + local c_sand = minetest.get_content_id("default:sand") + + --Snow biomes are found at 0.53 and greater perlin noise. + minetest.register_on_generated(function(minp, maxp, seed) + --if maxp.y >= -10 and maxp.y > snow.min_height then + + --Start timer + local t1 = os.clock() + local in_biome = false + + --Load Voxel Manipulator + local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") + local a = VoxelArea:new{ + MinEdge={x=emin.x, y=emin.y, z=emin.z}, + MaxEdge={x=emax.x, y=emax.y, z=emax.z}, + } + local data = vm:get_data() + + local debug = snow.debug + local min_height = snow.min_height + + --Should make things a bit faster. + local env = minetest.env + + + -- Assume X and Z lengths are equal + local divlen = 16 + local divs = (maxp.x-minp.x)+1; + local x0 = minp.x + local z0 = minp.z + local x1 = maxp.x + local z1 = maxp.z + + + --Get map specific perlin noise. + local perlin1 = env:get_perlin(112,3, 0.5, 150) + + --Speed hack: checks the corners and middle of the chunk for "snow biome". + --[[if not ( perlin1:get2d( {x=x0, y=z0} ) > 0.53 ) --top left + and not ( perlin1:get2d( { x = x0 + ( (x1-x0)/2), y=z0 } ) > 0.53 )--top middle + and not (perlin1:get2d({x=x1, y=z1}) > 0.53) --bottom right + and not (perlin1:get2d({x=x1, y=z0+((z1-z0)/2)}) > 0.53) --right middle + and not (perlin1:get2d({x=x0, y=z1}) > 0.53) --bottom left + and not (perlin1:get2d({x=x1, y=z0}) > 0.53) --top right + and not (perlin1:get2d({x=x0+((x1-x0)/2), y=z1}) > 0.53) --left middle + and not (perlin1:get2d({x=(x1-x0)/2, y=(z1-z0)/2}) > 0.53) --middle + and not (perlin1:get2d({x=x0, y=z1+((z1-z0)/2)}) > 0.53) then --bottom middle + return + end]] + + --Choose a biome types. + local pr = PseudoRandom(seed+57) + local biome + + --Land biomes + biome = pr:next(1, 5) + local snowy = biome == 1 --spawns alot of snow + local plain = biome == 2 --spawns not much + local alpine = biome == 3 --rocky terrain + -- biome == 4 or biome == 5 -- normal biome + + --Water biomes + biome2 = pr:next(1, 5) + local cool = biome == 1 --only spawns ice on edge of water + local icebergs = biome == 2 + local icesheet = biome == 3 + local icecave = biome == 4 + local icehole = biome == 5 --icesheet with holes + + --Misc biome settings. + local icy = pr:next(1, 2) == 2 --If enabled spawns ice in sand instead of snow blocks. + local mossy = pr:next(1,2) == 1 --Spawns moss in snow. + local shrubs = pr:next(1,2) == 1 --Spawns dry shrubs in snow. + local pines = pr:next(1,2) == 1 --spawns pines. + + --Debugging function + local biomeToString = function(num,num2) + local biome, biome2 + if num == 1 then biome = "snowy" + elseif num == 2 then biome = "plain" + elseif num == 3 then biome = "alpine" + elseif num == 4 or num == 5 then biome = "normal" + else biome = "unknown "..num end + + if num2 == 1 then biome2 = "cool" + elseif num2 == 2 then biome2 = "icebergs" + elseif num2 == 3 then biome2 = "icesheet" + elseif num2 == 4 then biome2 = "icecave" + elseif num2 == 5 then biome2 = "icehole" + else biome2 = "unknown "..num end + + return biome, biome2 + end + + local spawn_pine = snow.voxelmanip_pine + local smooth = snow.smooth_biomes + local legacy = snow.legacy + + --Reseed random. + pr = PseudoRandom(seed+68) + + --[[if alpine then + local trees = env:find_nodes_in_area(minp, maxp, {"default:leaves","default:tree"}) + for i,v in pairs(trees) do + env:remove_node(v) + end + end]] + + --Loop through chunk. + for x = minp.x, maxp.x do + for z = minp.z, maxp.z do + + --Check if we are in a "Snow biome" + local in_biome = false + local test = perlin1:get2d({x=x, y=z}) + if smooth and (not snowy) and (test > 0.73 or (test > 0.43 and pr:next(0,29) > (0.73 - test) * 100 )) then + in_biome = true + elseif (not smooth or snowy) and test > 0.53 then + in_biome = true + end + + + if in_biome then + + local perlin2 = env:get_perlin(322345,3, 0.5, 80) + local icetype = perlin2:get2d({x=x, y=z}) + local cool = icetype > 0 --only spawns ice on edge of water + local icebergs = icetype > -0.2 and icetype <= 0 + local icehole = icetype > -0.4 and icetype <= -0.2 + local icesheet = icetype > -0.6 and icetype <= -0.4 + local icecave = icetype <= -0.6 + + --if not plain or pr:next(1,12) == 1 then + + -- Find ground level (0...15) + local ground_y = nil + for y=maxp.y,minp.y,-1 do + local n = data[a:index(x, y, z)] + if n ~= c_air and n ~= c_ignore then + ground_y = y + break + end + end + + if ground_y then --and ground_y > min_height then + + -- Snowy biome stuff + local node = a:index(x, ground_y, z) + local abovenode = a:index(x, ground_y+1, z) + local belownode = a:index(x, ground_y+2, z) + + if ground_y and data[node] == c_dirt_with_grass then + --local veg + --if legacy and mossy and pr:next(1,10) == 1 then veg = 1 end + if alpine then + --Gets rid of dirt + data[abovenode] = c_snow + for y=ground_y,-6,-1 do + local stone = a:index(x, y, z) + if data[stone] == "default:stone" then + break + else + data[stone] = c_stone + end + end + elseif (shrubs and pr:next(1,28) == 1) then + --Spawns dry shrubs. + data[node] = c_dirt_with_snow + data[abovenode] = c_dry_shrub + elseif pines and pr:next(1,36) == 1 then + --Spawns pines. + data[node] = c_dirt_with_snow + spawn_pine({x=x, y=ground_y+1, z=z},a,data) + --elseif snowy then + --Spawns snow blocks. + --env:add_node({x=x,y=ground_y+1,z=z}, {name="snow:snow_block"}) + --data[aanode] = c_snow + else + --Spawns snow. + data[node] = c_dirt_with_snow + data[abovenode] = c_snow + end + elseif ground_y and data[belownode] == c_sand then + --Spawns ice in sand if icy, otherwise spawns snow on top. + if not icy then + data[node] = c_snow + else + data[belownode] = c_ice + end + elseif ground_y and data[node] == c_leaves then + data[abovenode] = c_snow + elseif ground_y and data[node] == c_papyrus then + for i=ground_y, ground_y-4, -1 do + local papyrus = a:index(x, y, z) + if data[papyrus] == c_papyrus then + local papyrusabove = a:index(x, ground_y, z) + data[papyrusabove] = c_snow + data[papyrus] = c_snow_block + end + end + elseif ground_y and data[node] == c_water then + if not icesheet and not icecave and not icehole then + --Coastal ice. + local x1 = data[a:index(x+1,ground_y,z)] + local z1 = data[a:index(x,ground_y,z+1)] + local xz1 = data[a:index(x+1,ground_y,z+1)] + local xz2 = data[a:index(x-1,ground_y,z-1)] + local x2 = data[a:index(x-1,ground_y,z)] + local z2 = data[a:index(x,ground_y,z-1)] + local y = data[a:index(x,ground_y-1,z)] + local rand = pr:next(1,4) == 1 + if + ((x1 and x1 ~= c_water and x1 ~= c_ice and x1 ~= c_air and x1 ~= c_ignore) or ((cool or icebergs) and x1 == c_ice and rand)) or + ((z1 and z1 ~= c_water and z1 ~= c_ice and z1 ~= c_air and z1 ~= c_ignore) or ((cool or icebergs) and z1 == c_ice and rand)) or + ((xz1 and xz1 ~= c_water and xz1 ~= c_ice and xz1 ~= c_air and xz1 ~= c_ignore) or ((cool or icebergs) and xz1 == c_ice and rand)) or + ((xz2 and xz2 ~= c_water and xz2 ~= c_ice and xz2 ~= c_air and xz2 ~= c_ignore) or ((cool or icebergs) and xz2 == c_ice and rand)) or + ((x2 and x2 ~= c_water and x2 ~= c_ice and x2 ~= c_air and x2 ~= c_ignore) or ((cool or icebergs) and x2 == c_ice and rand)) or + ((z2 and z2 ~= c_water and z2 ~= c_ice and z2 ~= c_air and z2 ~= c_ignore) or ((cool or icebergs) and z2 == c_ice and rand)) or + (y ~= c_water and y ~= c_ice and y ~= "air") or (pr:next(1,6) == 1 and icebergs) then + data[node] = c_ice + end + else + --Icesheets, Broken icesheet, Icecaves + if (icehole and pr:next(1,10) > 1) or icecave or icesheet then + data[node] = c_ice + end + if icecave then + --Gets rid of water underneath ice + for y=ground_y-1,-60,-1 do + local water = a:index(x, y, z) + if data[water] ~= c_water then + break + else + data[water] = c_air + end + end + end + end + --~ elseif ground_y and node.name == "snow:snow" and node.name ~= "snow:ice" then + --~ --Abort genaration. + --~ local name = env:get_node({x=x,y=ground_y-1,z=z}).name + --~ if name ~= "default:leaves" and name ~= "snow:needles" then + --~ if debug then + --~ print(biomeToString(biome)..": snow found ABORTED!") + --~ end + --~ return + --~ end]] + end + end + --end + end + end + end + if debug then + biome_string,biome2_string = biomeToString(biome,biome2) + print(biome_string.." and "..biome2_string..": Snow Biome Genarated near x"..minp.x.." z"..minp.z) + end + vm:set_data(data) + + vm:calc_lighting( + {x=minp.x-16, y=minp.y, z=minp.z-16}, + {x=maxp.x+16, y=maxp.y, z=maxp.z+16} + ) + + vm:write_to_map(data) + + print(string.format("elapsed time: %.2fms", (os.clock() - t1) * 1000)) + --end + end) +end