218738812e
Without this fix falling nodes (e.g. sand) do not work correctly. For example, placing sand on top of water the sand will drop and disappear.
295 lines
9.5 KiB
Lua
295 lines
9.5 KiB
Lua
-- caverealms v.0.3 by HeroOfTheWinds
|
|
-- original cave code modified from paramat's subterrain
|
|
-- For Minetest 0.4.8 stable
|
|
-- Depends default
|
|
-- License: code WTFPL
|
|
|
|
|
|
caverealms = {} --create a container for functions and constants
|
|
|
|
--grab a shorthand for the filepath of the mod
|
|
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
|
|
|
--load companion lua files
|
|
dofile(modpath.."/config.lua") --configuration file; holds various constants
|
|
dofile(modpath.."/crafting.lua") --crafting recipes
|
|
dofile(modpath.."/falling_ice.lua") --complicated function for falling icicles
|
|
dofile(modpath.."/nodes.lua") --node definitions
|
|
dofile(modpath.."/functions.lua") --function definitions
|
|
|
|
-- Parameters
|
|
|
|
local YMIN = caverealms.config.ymin -- Approximate realm limits.
|
|
local YMAX = caverealms.config.ymax
|
|
local TCAVE = caverealms.config.tcave --0.5 -- Cave threshold. 1 = small rare caves, 0.5 = 1/3rd ground volume, 0 = 1/2 ground volume
|
|
local BLEND = 128 -- Cave blend distance near YMIN, YMAX
|
|
|
|
local STAGCHA = caverealms.config.stagcha --0.002 --chance of stalagmites
|
|
local STALCHA = caverealms.config.stalcha --0.003 --chance of stalactites
|
|
local CRYSTAL = caverealms.config.crystal --0.007 --chance of glow crystal formations
|
|
local GEMCHA = caverealms.config.gemcha --0.03 --chance of small glow gems
|
|
local MUSHCHA = caverealms.config.mushcha --0.04 --chance of mushrooms
|
|
local MYCCHA = caverealms.config.myccha --0.03 --chance of mycena mushrooms
|
|
local WORMCHA = caverealms.config.wormcha --0.03 --chance of glow worms
|
|
local GIANTCHA = caverealms.config.giantcha --0.001 -- chance of giant mushrooms
|
|
local ICICHA = caverealms.config.icicha --0.035 -- chance of icicles
|
|
|
|
-- 3D noise for caves
|
|
|
|
local np_cave = {
|
|
offset = 0,
|
|
scale = 1,
|
|
spread = {x=512, y=256, z=512}, -- squashed 2:1
|
|
seed = 59033,
|
|
octaves = 6,
|
|
persist = 0.63
|
|
}
|
|
|
|
-- 3D noise for wave
|
|
|
|
local np_wave = {
|
|
offset = 0,
|
|
scale = 1,
|
|
spread = {x=256, y=256, z=256},
|
|
seed = -400000000089,
|
|
octaves = 3,
|
|
persist = 0.67
|
|
}
|
|
|
|
-- 2D noise for biome
|
|
|
|
local np_biome = {
|
|
offset = 0,
|
|
scale = 1,
|
|
spread = {x=250, y=250, z=250},
|
|
seed = 9130,
|
|
octaves = 3,
|
|
persist = 0.5
|
|
}
|
|
|
|
-- Stuff
|
|
|
|
subterrain = {}
|
|
|
|
local yblmin = YMIN + BLEND * 1.5
|
|
local yblmax = YMAX - BLEND * 1.5
|
|
|
|
-- On generated function
|
|
|
|
minetest.register_on_generated(function(minp, maxp, seed)
|
|
--if out of range of caverealms limits
|
|
if minp.y > YMAX or maxp.y < YMIN then
|
|
return --quit; otherwise, you'd have stalagmites all over the place
|
|
end
|
|
|
|
--easy reference to commonly used values
|
|
local t1 = os.clock()
|
|
local x1 = maxp.x
|
|
local y1 = maxp.y
|
|
local z1 = maxp.z
|
|
local x0 = minp.x
|
|
local y0 = minp.y
|
|
local z0 = minp.z
|
|
|
|
print ("[caverealms] chunk minp ("..x0.." "..y0.." "..z0..")") --tell people you are generating a chunk
|
|
|
|
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
|
local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
|
|
local data = vm:get_data()
|
|
|
|
--grab content IDs
|
|
local c_air = minetest.get_content_id("air")
|
|
local c_stone = minetest.get_content_id("default:stone")
|
|
local c_water = minetest.get_content_id("default:water_source")
|
|
local c_lava = minetest.get_content_id("default:lava_source")
|
|
local c_ice = minetest.get_content_id("default:ice")
|
|
local c_thinice = minetest.get_content_id("caverealms:thin_ice")
|
|
local c_crystal = minetest.get_content_id("caverealms:glow_crystal")
|
|
local c_gem1 = minetest.get_content_id("caverealms:glow_gem")
|
|
local c_gem2 = minetest.get_content_id("caverealms:glow_gem_2")
|
|
local c_gem3 = minetest.get_content_id("caverealms:glow_gem_3")
|
|
local c_gem4 = minetest.get_content_id("caverealms:glow_gem_4")
|
|
local c_gem5 = minetest.get_content_id("caverealms:glow_gem_5")
|
|
local c_moss = minetest.get_content_id("caverealms:stone_with_moss")
|
|
local c_lichen = minetest.get_content_id("caverealms:stone_with_lichen")
|
|
local c_algae = minetest.get_content_id("caverealms:stone_with_algae")
|
|
local c_fungus = minetest.get_content_id("caverealms:fungus")
|
|
local c_mycena = minetest.get_content_id("caverealms:mycena")
|
|
local c_worm = minetest.get_content_id("caverealms:glow_worm")
|
|
local c_iciu = minetest.get_content_id("caverealms:icicle_up")
|
|
local c_icid = minetest.get_content_id("caverealms:icicle_down")
|
|
|
|
--mandatory values
|
|
local sidelen = x1 - x0 + 1 --length of a mapblock
|
|
local chulens = {x=sidelen, y=sidelen, z=sidelen} --table of chunk edges
|
|
local minposxyz = {x=x0, y=y0, z=z0} --bottom corner
|
|
local minposxz = {x=x0, y=z0} --2D bottom corner
|
|
|
|
local nvals_cave = minetest.get_perlin_map(np_cave, chulens):get3dMap_flat(minposxyz) --cave noise for structure
|
|
local nvals_wave = minetest.get_perlin_map(np_wave, chulens):get3dMap_flat(minposxyz) --wavy structure of cavern ceilings and floors
|
|
local nvals_biome = minetest.get_perlin_map(np_biome, chulens):get2dMap_flat({x=x0+150, y=z0+50}) --2D noise for biomes (will be 3D humidity/temp later)
|
|
|
|
local nixyz = 1 --3D node index
|
|
local nixz = 1 --2D node index
|
|
local nixyz2 = 1 --second 3D index for second loop
|
|
|
|
for z = z0, z1 do -- for each xy plane progressing northwards
|
|
--structure loop
|
|
for y = y0, y1 do -- for each x row progressing upwards
|
|
local tcave --declare variable
|
|
--determine the overal cave threshold
|
|
if y < yblmin then
|
|
tcave = TCAVE + ((yblmin - y) / BLEND) ^ 2
|
|
elseif y > yblmax then
|
|
tcave = TCAVE + ((y - yblmax) / BLEND) ^ 2
|
|
else
|
|
tcave = TCAVE
|
|
end
|
|
local vi = area:index(x0, y, z) --current node index
|
|
for x = x0, x1 do -- for each node do
|
|
if (nvals_cave[nixyz] + nvals_wave[nixyz])/2 > tcave then --if node falls within cave threshold
|
|
data[vi] = c_air --hollow it out to make the cave
|
|
end
|
|
--increment indices
|
|
nixyz = nixyz + 1
|
|
vi = vi + 1
|
|
end
|
|
end
|
|
|
|
--decoration loop
|
|
for y = y0, y1 do -- for each x row progressing upwards
|
|
local tcave --same as above
|
|
if y < yblmin then
|
|
tcave = TCAVE + ((yblmin - y) / BLEND) ^ 2
|
|
elseif y > yblmax then
|
|
tcave = TCAVE + ((y - yblmax) / BLEND) ^ 2
|
|
else
|
|
tcave = TCAVE
|
|
end
|
|
local vi = area:index(x0, y, z)
|
|
for x = x0, x1 do -- for each node do
|
|
|
|
--determine biome
|
|
local biome = false --preliminary declaration
|
|
n_biome = nvals_biome[nixz] --make an easier reference to the noise
|
|
--compare noise values to determine a biome
|
|
if n_biome >= 0 and n_biome < 0.5 then
|
|
biome = 1 --moss
|
|
elseif n_biome <= -0.5 then
|
|
biome = 2 --fungal
|
|
elseif n_biome >= 0.5 then
|
|
if n_biome >= 0.7 then
|
|
biome = 5 --deep glaciated
|
|
else
|
|
biome = 4 --glaciated
|
|
end
|
|
else
|
|
biome = 3 --algae
|
|
end
|
|
|
|
if math.floor(((nvals_cave[nixyz2] + nvals_wave[nixyz2])/2)*100) == math.floor(tcave*100) then
|
|
--ceiling
|
|
local ai = area:index(x,y+1,z) --above index
|
|
if data[ai] == c_stone and data[vi] == c_air then --ceiling
|
|
if math.random() < ICICHA and (biome == 4 or biome == 5) then
|
|
local bi = area:index(x,y-1,z)
|
|
data[bi] = c_icid
|
|
end
|
|
if math.random() < WORMCHA then
|
|
data[vi] = c_worm
|
|
local bi = area:index(x,y-1,z)
|
|
data[bi] = c_worm
|
|
if math.random(2) == 1 then
|
|
local bbi = area:index(x,y-2,z)
|
|
data[bbi] = c_worm
|
|
if math.random(2) ==1 then
|
|
local bbbi = area:index(x,y-3,z)
|
|
data[bbbi] = c_worm
|
|
end
|
|
end
|
|
end
|
|
if math.random() < STALCHA then
|
|
caverealms:stalactite(x,y,z, area, data)
|
|
end
|
|
if math.random() < CRYSTAL then
|
|
caverealms:crystal_stalactite(x,y,z, area, data, biome)
|
|
end
|
|
end
|
|
--ground
|
|
local bi = area:index(x,y-1,z) --below index
|
|
if data[bi] == c_stone and data[vi] == c_air then --ground
|
|
local ai = area:index(x,y+1,z)
|
|
--place floor material, add plants/decorations
|
|
if biome == 1 then
|
|
data[vi] = c_moss
|
|
if math.random() < GEMCHA then
|
|
-- gems of random size
|
|
local gems = { c_gem1, c_gem2, c_gem3, c_gem4, c_gem5 }
|
|
local gidx = math.random(1, 12)
|
|
if gidx > 5 then
|
|
gidx = 1
|
|
end
|
|
data[ai] = gems[gidx]
|
|
end
|
|
elseif biome == 2 then
|
|
data[vi] = c_lichen
|
|
if math.random() < MUSHCHA then --mushrooms
|
|
data[ai] = c_fungus
|
|
end
|
|
if math.random() < MYCCHA then --mycena mushrooms
|
|
data[ai] = c_mycena
|
|
end
|
|
if math.random() < GIANTCHA then --giant mushrooms
|
|
caverealms:giant_shroom(x, y, z, area, data)
|
|
end
|
|
elseif biome == 3 then
|
|
data[vi] = c_algae
|
|
elseif biome == 4 then
|
|
data[vi] = c_thinice
|
|
local bi = area:index(x,y-1,z)
|
|
data[bi] = c_thinice
|
|
if math.random() < ICICHA then --if glaciated, place icicles
|
|
data[ai] = c_iciu
|
|
end
|
|
elseif biome == 5 then
|
|
data[vi] = c_ice
|
|
local bi = area:index(x,y-1,z)
|
|
data[bi] = c_ice
|
|
if math.random() < ICICHA then --if glaciated, place icicles
|
|
data[ai] = c_iciu
|
|
end
|
|
end
|
|
|
|
if math.random() < STAGCHA then
|
|
caverealms:stalagmite(x,y,z, area, data)
|
|
end
|
|
if math.random() < CRYSTAL then
|
|
caverealms:crystal_stalagmite(x,y,z, area, data, biome)
|
|
end
|
|
end
|
|
|
|
end
|
|
nixyz2 = nixyz2 + 1
|
|
nixz = nixz + 1
|
|
vi = vi + 1
|
|
end
|
|
nixz = nixz - sidelen --shift the 2D index back
|
|
end
|
|
nixz = nixz + sidelen --shift the 2D index up a layer
|
|
end
|
|
|
|
--send data back to voxelmanip
|
|
vm:set_data(data)
|
|
--calc lighting
|
|
vm:set_lighting({day=0, night=0})
|
|
vm:calc_lighting()
|
|
--write it to world
|
|
vm:write_to_map(data)
|
|
|
|
local chugent = math.ceil((os.clock() - t1) * 1000) --grab how long it took
|
|
print ("[caverealms] "..chugent.." ms") --tell people how long
|
|
end)
|
|
|
|
|
|
print("[caverealms] loaded!")
|