Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- paragen 0.2.0 by paramat
- -- For latest stable Minetest and back to 0.4.7, requires default snow nodes
- -- Depends default
- -- Licenses: Code WTFPL. Textures: CC BY-SA
- -- Variables
- local ONGEN = true -- (true / false) Enable / disable generation.
- local XMIN = -16000 -- Approx West edge. -- These 6 parameters will be rounded down or up to chunk edges.
- local XMAX = 16000 -- Approx East edge.
- local ZMIN = -16000 -- Approx South edge.
- local ZMAX = 16000 -- Approx North edge.
- local YMIN = 12000 -- Approx bottom. -- Terrain is automatically centered between YMIN and YMAX.
- local YMAX = 14000 -- Approx top.
- local WATY = 13000 -- Water surface y.
- local GRADC = 13040 -- Temperature and humidity gradient centre y.
- local CLOUDY = 13080 -- Cloud y.
- local SANY = 13002 -- Sandline average y of beach top.
- local SANA = 6 -- 6 -- Sandline amplitude.
- local SANR = 2 -- 2 -- Sandline randomness.
- local VSCALE = 160 -- Vertical scale of terrain.
- local PERSAV = 0.5 -- 0.5 -- Persistence average. Terrain roughness.
- local PERSAMP = 0.1 -- 0.1 -- Persistence amplitude. Roughness variation.
- local STAV = 0.05 -- 0.04 -- Stone threshold average. Fine material depth.
- local STAMP = 0.02 -- 0.02 -- Stone threshold amplitude. Depth variation.
- local FISTS = 0.01 -- 0.01 -- Fissure noise threshold surface. Fissure size at surface.
- local CAVTS = 8.0 -- 2.0 -- Cave noise threshold surface. Cave size at surface.
- local FISTU = 0.03 -- 0.03 -- Fissure threshold underground. Fissure size underground.
- local CAVTU = 0.5 -- 0.5 -- Cave threshold underground. Cave size underground.
- local HITET = 0.35 -- -- Desert / savanna / rainforest temperature noise threshold.
- local LOTET = -0.45 -- -- Tundra / taiga temperature noise threshold.
- local HIWET = 0.35 -- -- Wet grassland / rainforest wetness noise threshold.
- local LOWET = -0.45 -- -- Tundra / dry grassland / desert wetness noise threshold.
- local TGRAD = 160 -- 160 -- Vertical temperature gradient. -- All 3 fall with altitude.
- local HGRAD = 160 -- 160 -- Vertical humidity gradient.
- local STGRAD = 1600 -- 160 -- Stone threshold gradient.
- local CHUT = 0.0 -- -- Cloud humidity threshold.
- local CHUTH = 0.8 -- -- Cloud humidity threshold high, for dark clouds.
- local TUNGRACHA = 145 -- 145 -- Dry shrub 1/x chance per full node in tundra.
- local TAIPINCHA = 49 -- 49 -- Pine 1/x chance per full node in taiga.
- local DRYGRACHA = 2 -- 2 -- Dry shrub 1/x chance per full node in dry grasslands.
- local DECAPPCHA = 85 -- 85 -- Appletree sapling 1/x chance per full node in deciduous forest.
- local WETGRACHA = 2 -- 2 -- Junglegrass 1/x chance per full node in wet grasslands.
- local DESCACCHA = 421 -- 421 -- Cactus 1/x chance per full node in desert.
- local DESGRACHA = 265 -- 265 -- Dry shrub 1/x chance per full node in desert.
- local SAVGRACHA = 3 -- 3 -- Dry shrub 1/x chance per full node in savanna.
- local SAVTRECHA = 361 -- 361 -- Savanna tree 1/x chance per full node in savanna.
- local RAIJUNCHA = 25 -- 25 -- Jungletree 1/x chance per full node in rainforest.
- local DUNGRACHA = 9 -- -- Dry shrub 1/x chance per full node in dunes.
- local PININT = 67 -- 67 -- Pine from sapling abm interval in seconds.
- local PINCHA = 11 -- 11 -- 1/x chance per node.
- local JUNINT = 71 -- 71 -- Jungletree from sapling abm interval in seconds.
- local JUNCHA = 11 -- 11 -- 1/x chance per node.
- local SAVINT = 73 -- 73 -- Jungletree from sapling abm interval in seconds.
- local SAVCHA = 11 -- 11 -- 1/x chance per node.
- -- 3D Perlin1 for terrain
- local perl1 = {
- SEED1 = 5829058,
- OCTA1 = 7, --
- SCAL1 = 512, --
- }
- -- 2D Perlin2 for alt terrain
- local perl2 = {
- SEED2 = 76906,
- OCTA2 = 7, --
- SCAL2 = 414, --
- }
- -- 3D Perlin3 for terrain select
- local perl3 = {
- SEED3 = 848,
- OCTA3 = 5, --
- PERS3 = 0.5, --
- SCAL3 = 256, --
- }
- -- 3D Perlin4 for fissures and caves
- local perl4 = {
- SEED4 = 98275470284,
- OCTA4 = 6, --
- PERS4 = 0.5, --
- SCAL4 = 207, --
- }
- -- 3D Perlin5 for perlin1 perlin2 persistence, stone depth, sandline
- local perl5 = {
- SEED5 = 7028411255342,
- OCTA5 = 4, --
- PERS5 = 0.5, --
- SCAL5 = 414, --
- }
- -- 3D Perlin6 for temperature
- local perl6 = {
- SEED6 = 7,
- OCTA6 = 2, --
- PERS6 = 0.5, --
- SCAL6 = 512, --
- }
- -- 3D Perlin7 for humidity
- local perl7 = {
- SEED7 = 900011676,
- OCTA7 = 2, --
- PERS7 = 0.5, --
- SCAL7 = 512, --
- }
- -- Nodes
- minetest.register_node("paragen:redstone", {
- description = "PG Redstone",
- tiles = {"paragen_redstone.png"},
- groups = {cracky=3},
- sounds = default.node_sound_stone_defaults(),
- })
- minetest.register_node("paragen:stone", {
- description = "PG Stone",
- tiles = {"default_stone.png"},
- groups = {cracky=3},
- sounds = default.node_sound_stone_defaults(),
- })
- minetest.register_node("paragen:permafrost", {
- description = "PG Permafrost",
- tiles = {"paragen_permafrost.png"},
- groups = {crumbly=1},
- drop = "default:dirt",
- sounds = default.node_sound_dirt_defaults(),
- })
- minetest.register_node("paragen:drygrass", {
- description = "PG Dirt With Dry Grass",
- tiles = {"paragen_drygrass.png", "default_dirt.png", "paragen_drygrass.png"},
- groups = {crumbly=3,soil=1},
- drop = "default:dirt",
- sounds = default.node_sound_dirt_defaults({
- footstep = {name="default_grass_footstep", gain=0.4},
- }),
- })
- minetest.register_node("paragen:cloud", {
- drawtype = "glasslike",
- tiles = {"paragen_cloud.png"},
- paramtype = "light",
- sunlight_propagates = true,
- walkable = false,
- pointable = false,
- diggable = false,
- buildable_to = true,
- post_effect_color = {a=127, r=255, g=255, b=255},
- groups = {not_in_creative_inventory=1},
- })
- minetest.register_node("paragen:darkcloud", {
- drawtype = "glasslike",
- tiles = {"paragen_darkcloud.png"},
- paramtype = "light",
- sunlight_propagates = true,
- walkable = false,
- pointable = false,
- diggable = false,
- buildable_to = true,
- post_effect_color = {a=127, r=255, g=255, b=255},
- groups = {not_in_creative_inventory=1},
- })
- minetest.register_node("paragen:pleaf", {
- description = "PG Pine Needles",
- visual_scale = 1.3,
- tiles = {"paragen_pleaf.png"},
- paramtype = "light",
- groups = {snappy=3, flammable=2},
- drop = {
- max_items = 1,
- items = {
- {items = {"paragen:psapling"}, rarity = 20},
- {items = {"paragen:pleaf"}}
- }
- },
- sounds = default.node_sound_leaves_defaults(),
- })
- minetest.register_node("paragen:psapling", {
- description = "PG Pine Sapling",
- drawtype = "plantlike",
- visual_scale = 1.0,
- tiles = {"paragen_psapling.png"},
- inventory_image = "paragen_psapling.png",
- wield_image = "paragen_psapling.png",
- paramtype = "light",
- walkable = false,
- groups = {snappy=2,dig_immediate=3,flammable=2},
- sounds = default.node_sound_defaults(),
- })
- minetest.register_node("paragen:sleaf", {
- description = "PG Savanna Tree Leaves",
- visual_scale = 1.3,
- tiles = {"paragen_sleaf.png"},
- paramtype = "light",
- groups = {snappy=3, flammable=2},
- drop = {
- max_items = 1,
- items = {
- {items = {"paragen:ssapling"}, rarity = 20},
- {items = {"paragen:sleaf"}}
- }
- },
- sounds = default.node_sound_leaves_defaults(),
- })
- minetest.register_node("paragen:ssapling", {
- description = "PG Savanna Tree Sapling",
- drawtype = "plantlike",
- visual_scale = 1.0,
- tiles = {"paragen_ssapling.png"},
- inventory_image = "paragen_ssapling.png",
- wield_image = "paragen_ssapling.png",
- paramtype = "light",
- walkable = false,
- groups = {snappy=2,dig_immediate=3,flammable=2},
- sounds = default.node_sound_defaults(),
- })
- -- Stuff
- paragen = {}
- local xminq = (80 * math.floor((XMIN + 32) / 80)) - 32
- local yminq = (80 * math.floor((YMIN + 32) / 80)) - 32
- local zminq = (80 * math.floor((ZMIN + 32) / 80)) - 32
- local xmaxq = (80 * math.floor((XMAX + 32) / 80)) + 47
- local ymaxq = (80 * math.floor((YMAX + 32) / 80)) + 47
- local zmaxq = (80 * math.floor((ZMAX + 32) / 80)) + 47
- local gradcen = math.floor((ymaxq + yminq) / 2)
- local cloudyq = (80 * math.floor((CLOUDY + 32) / 80)) - 32
- -- On generated function
- if ONGEN then
- minetest.register_on_generated(function(minp, maxp, seed)
- if minp.y >= yminq and maxp.y <= ymaxq then
- local env = minetest.env
- local perlin3 = env:get_perlin(perl3.SEED3, perl3.OCTA3, perl3.PERS3, perl3.SCAL3)
- local perlin4 = env:get_perlin(perl4.SEED4, perl4.OCTA4, perl4.PERS4, perl4.SCAL4)
- local perlin5 = env:get_perlin(perl5.SEED5, perl5.OCTA5, perl5.PERS5, perl5.SCAL5)
- local perlin6 = env:get_perlin(perl6.SEED6, perl6.OCTA6, perl6.PERS6, perl6.SCAL6)
- local perlin7 = env:get_perlin(perl7.SEED7, perl7.OCTA7, perl7.PERS7, perl7.SCAL7)
- local x1 = maxp.x
- local y1 = maxp.y
- local z1 = maxp.z
- local x0 = minp.x
- local y0 = minp.y
- local z0 = minp.z
- 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 nodeid = {}
- nodeid.sand = minetest.get_content_id("default:sand")
- nodeid.shrub = minetest.get_content_id("default:dry_shrub")
- nodeid.snowblock = minetest.get_content_id("default:snowblock")
- nodeid.snow = minetest.get_content_id("default:snow")
- nodeid.desertsand = minetest.get_content_id("default:desert_sand")
- nodeid.cactus = minetest.get_content_id("default:cactus")
- nodeid.permafrost = minetest.get_content_id("paragen:permafrost")
- nodeid.drygrass = minetest.get_content_id("paragen:drygrass")
- nodeid.dirt = minetest.get_content_id("default:dirt")
- nodeid.dirtwgrass = minetest.get_content_id("default:dirt_with_grass")
- nodeid.junglegrass = minetest.get_content_id("default:junglegrass")
- nodeid.sapling = minetest.get_content_id("default:sapling")
- nodeid.redstone = minetest.get_content_id("paragen:redstone")
- nodeid.stone = minetest.get_content_id("paragen:stone")
- nodeid.sandstone = minetest.get_content_id("default:sandstone")
- nodeid.ice = minetest.get_content_id("default:ice")
- nodeid.water = minetest.get_content_id("default:water_source")
- nodeid.cloud = minetest.get_content_id("paragen:cloud")
- nodeid.darkcloud = minetest.get_content_id("paragen:darkcloud")
- for x = x0, x1 do -- for each plane do
- print ("[paragen] "..(x - x0 + 1).." ("..minp.x.." "..minp.y.." "..minp.z..")")
- for z = z0, z1 do -- for each column do
- local sol = false -- node is solid
- local des = false -- desert biome
- local sav = false -- savanna biome
- local rai = false -- rainforest biome
- local wet = false -- wet grassland biome
- local dry = false -- dry grassland biome
- local dec = false -- deciduous forest biome
- local tun = false -- tundra biome
- local tai = false -- taiga forest biome
- local noise5c = perlin5:get2d({x=x-777,y=z-777}) -- beach top
- local sandy = SANY + noise5c * SANA + math.random(SANR)
- for y = y1, y0, -1 do -- working downwards through column for each node do
- local vi = a:index(x, y, z) -- LVM index for node
- local noise5 = perlin5:get3d({x=x,y=y,z=z}) -- persistence
- local pepers = PERSAV + noise5 * PERSAMP
- local noise5b = perlin5:get2d({x=x+777,y=z+777}) -- stone threshold
- local stothr = STAV + noise5b * STAMP - (y - WATY) / STGRAD
- local noise3 = perlin3:get3d({x=x,y=y/2,z=z}) -- terrain select
- if noise3 > 0 then
- local perlin1 = env:get_perlin(perl1.SEED1, perl1.OCTA1, pepers, perl1.SCAL1)
- noise = perlin1:get3d({x=x,y=y,z=z})
- else
- local perlin2 = env:get_perlin(perl2.SEED2, perl2.OCTA2, pepers, perl2.SCAL2)
- noise = perlin2:get3d({x=x,y=y,z=z})
- end
- local grad = (gradcen - y) / VSCALE
- local density = noise + grad
- if density >= 0 or y == WATY then -- if terrain or at sea level then
- if density < 1 then
- fist = FISTS + density * (FISTU - FISTS)
- cavt = CAVTS + density * (CAVTU - CAVTS)
- else
- fist = FISTU
- cavt = CAVTU
- end
- local noise4 = perlin4:get3d({x=x,y=y,z=z}) -- fissures
- local noise4b = perlin4:get3d({x=x*2,y=y*2,z=z*2}) -- caves
- if math.abs(noise4) > fist and math.abs(noise4b) < cavt then -- if no fissures and no cave then
- if not sol then -- when solid node found under air decide or reset biome
- local noise6 = perlin6:get2d({x=x,y=z})
- local noise7 = perlin7:get2d({x=x,y=z})
- local temp = noise6 - (y - GRADC) / TGRAD
- local hum = noise7 - (y - GRADC) / HGRAD
- if temp > HITET + math.random() / 10 then
- if hum > HIWET + math.random() / 10 then
- rai = true
- elseif hum < LOWET + math.random() / 10 then
- des = true
- else
- sav = true
- end
- elseif temp < LOTET + math.random() / 10 then
- if hum < LOWET + math.random() / 10 then
- tun = true
- else
- tai = true
- end
- elseif hum > HIWET + math.random() / 10 then
- wet = true
- elseif hum < LOWET + math.random() / 10 then
- dry = true
- else
- dec = true
- end
- end
- if density >= 0 and density < stothr then -- if fine material then
- if y <= sandy then -- if beach or dunes
- data[vi] = nodeid.sand
- if not sol then
- if y >= WATY + 4 and math.random(DUNGRACHA) == 2 then
- data[vi] = nodeid.shrub
- elseif tai then
- data[vi] = nodeid.snowblock
- elseif tun then
- data[vi] = nodeid.snow
- end
- end
- elseif des then -- if desert
- data[vi] = nodeid.desertsand
- if not sol then
- if math.random(DESGRACHA) == 2 then
- data[vi] = nodeid.shrub
- elseif math.random(DESCACCHA) == 2 then
- for c = 1, math.random(1,6) do
- data[vi] = nodeid.cactus
- end
- end
- end
- elseif tun then -- if tundra
- data[vi] = nodeid.permafrost
- if not sol then
- if math.random(TUNGRACHA) == 2 then
- data[vi] = nodeid.shrub
- else
- data[vi] = nodeid.snow
- end
- end
- elseif dry or sav then -- dry grassland or savanna
- data[vi] = nodeid.drygrass
- if not sol then -- if surface node then
- data[vi] = nodeid.drygrass
- if dry and math.random(DRYGRACHA) == 2 then
- data[vi] = nodeid.shrub
- elseif sav and math.random(SAVGRACHA) == 2 then
- data[vi] = nodeid.shrub
- elseif sav and math.random(SAVTRECHA) == 2 then
- paragen_stree({x=x,y=y+1,z=z})
- end
- else -- underground node
- data[vi] = nodeid.dirt
- end
- else -- wet grasslands, taiga, deciduous forest, rainforest
- if not sol then
- data[vi] = nodeid.dirtwgrass
- if wet and math.random(WETGRACHA) == 2 then
- data[vi] = nodeid.junglegrass
- elseif dec and y > sandy and math.random(DECAPPCHA) == 2 then
- data[vi] = nodeid.sapling
- elseif tai then
- if math.random(TAIPINCHA) == 2 then
- paragen_pine({x=x,y=y+1,z=z})
- else
- data[vi] = nodeid.snowblock
- end
- elseif rai and math.random(RAIJUNCHA) == 2 then
- paragen_jtree({x=x,y=y+1,z=z})
- end
- else
- data[vi] = nodeid.dirt
- end
- end
- elseif density >= stothr then
- if (density >= stothr and density < 0.13) -- if normal rock strata
- or (density >= 0.19 and density < 0.23)
- or (density >= 0.32 and density < 0.37)
- or (density >= 0.47 and density < 0.60)
- or (density >= 0.69 and density < 0.73)
- or density >= 0.97 then
- if (des or sav) and density < 1.29 then
- data[vi] = nodeid.redstone
- else
- data[vi] = nodeid.stone
- end
- else -- sandstone strata
- data[vi] = nodeid.sandstone
- end
- elseif y == WATY then -- if at sea surface
- if tun or tai then
- data[vi] = nodeid.ice
- if tai then
- data[vi] = nodeid.snow
- end
- else
- data[vi] = nodeid.water
- end
- end
- if density >= stothr and (tun or tai) and not sol then -- snow on high rocky alpine biome
- if tai then
- data[vi] = nodeid.snowblock
- else
- data[vi] = nodeid.snow
- end
- end
- sol = true -- node was solid
- end
- elseif y < WATY then -- underwater
- data[vi] = nodeid.water
- else
- sol = false -- node was not solid
- end
- end
- end
- end
- if y0 == cloudyq then -- CLouds
- print ("[paragen] Clouds ("..minp.x.." "..minp.y.." "..minp.z..")")
- for i = 0, (x1 - x0), 16 do
- for k = 0, (z1 - z0), 16 do
- local noise7 = perlin7:get2d({x=x0+i,y=z0+k})
- local hum = noise7
- if (hum - CHUT) > math.random() then
- for a = 0, 15 do
- for b = 0, 15 do
- local x = x0 + i + a
- local z = z0 + k + b
- if env:get_node({x=x,y=CLOUDY,z=z}).name == "air" then
- if hum > CHUTH then
- data[vi] = nodeid.darkcloud
- else
- data[vi] = nodeid.cloud
- end
- end
- end
- end
- end
- end
- end
- 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)
- end
- end)
- end
- -- ABMs
- -- Pine sapling abm
- minetest.register_abm({
- nodenames = {"paragen:psapling"},
- interval = PININT,
- chance = PINCHA,
- action = function(pos, node, active_object_count, active_object_count_wider)
- paragen_pine(pos)
- if DEBUG then
- print ("[paragen] Pine sapling grows")
- end
- end,
- })
- -- Jungletree sapling abm
- minetest.register_abm({
- nodenames = {"paragen:jsapling"},
- interval = JUNINT,
- chance = JUNCHA,
- action = function(pos, node, active_object_count, active_object_count_wider)
- paragen_jtree(pos)
- if DEBUG then
- print ("[paragen] Jungletree sapling grows")
- end
- end,
- })
- -- Savanna tree sapling abm
- minetest.register_abm({
- nodenames = {"paragen:ssapling"},
- interval = SAVINT,
- chance = SAVCHA,
- action = function(pos, node, active_object_count, active_object_count_wider)
- paragen_stree(pos)
- if DEBUG then
- print ("[paragen] Savanna tree sapling grows")
- end
- end,
- })
- -- Functions
- -- Jungletree function
- function paragen_jtree(pos)
- local env = minetest.env
- local t = 12 + math.random(5) -- trunk height
- for j = -3, t do
- if j == math.floor(t * 0.7) or j == t then
- for i = -2, 2 do
- for k = -2, 2 do
- local absi = math.abs(i)
- local absk = math.abs(k)
- if math.random() > (absi + absk) / 16 then
- env:add_node({x=pos.x+i,y=pos.y+j+math.random(0, 1),z=pos.z+k},{name="default:jungleleaves"})
- end
- end
- end
- end
- env:add_node({x=pos.x,y=pos.y+j,z=pos.z},{name="default:jungletree"})
- end
- end
- -- Savanna tree function
- function paragen_stree(pos)
- local env = minetest.env
- local t = 4 + math.random(2) -- trunk height
- for j = -2, t do
- if j == t then
- for i = -3, 3 do
- for k = -3, 3 do
- local absi = math.abs(i)
- local absk = math.abs(k)
- if math.random() > (absi + absk) / 24 then
- env:add_node({x=pos.x+i,y=pos.y+j+math.random(0, 1),z=pos.z+k},{name="paragen:sleaf"})
- end
- end
- end
- end
- env:add_node({x=pos.x,y=pos.y+j,z=pos.z},{name="default:tree"})
- end
- end
- -- Pine tree function
- function paragen_pine(pos)
- local env = minetest.env
- local t = 10 + math.random(3) -- trunk height
- for i = -2, 2 do
- for k = -2, 2 do
- local absi = math.abs(i)
- local absk = math.abs(k)
- if absi >= absk then
- j = t - absi
- else
- j = t - absk
- end
- if math.random() > (absi + absk) / 16 then
- env:add_node({x=pos.x+i,y=pos.y+j+2,z=pos.z+k},{name="default:snow"})
- env:add_node({x=pos.x+i,y=pos.y+j+1,z=pos.z+k},{name="paragen:pleaf"})
- env:add_node({x=pos.x+i,y=pos.y+j-1,z=pos.z+k},{name="default:snow"})
- env:add_node({x=pos.x+i,y=pos.y+j-2,z=pos.z+k},{name="paragen:pleaf"})
- env:add_node({x=pos.x+i,y=pos.y+j-4,z=pos.z+k},{name="default:snow"})
- env:add_node({x=pos.x+i,y=pos.y+j-5,z=pos.z+k},{name="paragen:pleaf"})
- end
- end
- end
- for j = -3, t do
- env:add_node({x=pos.x,y=pos.y+j,z=pos.z},{name="default:tree"})
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement