Advertisement
Guest User

cavescale mod init.lua

a guest
Oct 13th, 2014
333
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.31 KB | None | 0 0
  1. -- Credit to SmallJoker for the yappy source which I used as a template when writing this.
  2. -- Credit to paramat for some ideas regarding cave generation using perlin noise.
  3. -- This code is free. Do whatever you want with it.
  4. -- If you make something cool, don't forget to share.
  5.  
  6. cavescale = {}
  7.  
  8. local SPREAD_XS = 32
  9. local SPREAD_S = 96
  10. local SPREAD_M = 256
  11. local SPREAD_L = 512
  12. local SQUASH = 0.7
  13. local SPREAD_GEOLOGY = 512
  14.  
  15. cavescale.perlin_caves_1_XS = {
  16.     offset = 0,
  17.     scale = 1,
  18.     spread = {x=SPREAD_XS, y=SPREAD_XS*SQUASH, z=SPREAD_XS},
  19.     octaves = 1,
  20.     seed = -1000,
  21.     persist = 0.5
  22. }
  23.  
  24. cavescale.perlin_caves_1_S = {
  25.     offset = 0,
  26.     scale = 1,
  27.     spread = {x=SPREAD_S, y=SPREAD_S*SQUASH, z=SPREAD_S},
  28.     octaves = 1,
  29.     seed = -2000,
  30.     persist = 0.5
  31. }
  32.  
  33. cavescale.perlin_caves_1_M = {
  34.     offset = 0,
  35.     scale = 1,
  36.     spread = {x=SPREAD_M, y=SPREAD_M*SQUASH, z=SPREAD_M},
  37.     octaves = 1,
  38.     seed = -3000,
  39.     persist = 0.5
  40. }
  41.  
  42. cavescale.perlin_caves_1_L = {
  43.     offset = 0,
  44.     scale = 1,
  45.     spread = {x=SPREAD_L, y=SPREAD_L*SQUASH, z=SPREAD_L},
  46.     octaves = 1,
  47.     seed = -4000,
  48.     persist = 0.5
  49. }
  50.  
  51. cavescale.perlin_caves_2_XS = {
  52.     offset = 0,
  53.     scale = 1,
  54.     spread = {x=SPREAD_XS, y=SPREAD_XS*SQUASH, z=SPREAD_XS},
  55.     octaves = 1,
  56.     seed = -5000,
  57.     persist = 0.5
  58. }
  59.  
  60. cavescale.perlin_caves_2_S = {
  61.     offset = 0,
  62.     scale = 1,
  63.     spread = {x=SPREAD_S, y=SPREAD_S*SQUASH, z=SPREAD_S},
  64.     octaves = 1,
  65.     seed = -6000,
  66.     persist = 0.5
  67. }
  68.  
  69. cavescale.perlin_caves_2_M = {
  70.     offset = 0,
  71.     scale = 1,
  72.     spread = {x=SPREAD_M, y=SPREAD_M*SQUASH, z=SPREAD_M},
  73.     octaves = 1,
  74.     seed = -7000,
  75.     persist = 0.5
  76. }
  77.  
  78. cavescale.perlin_caves_2_L = {
  79.     offset = 0,
  80.     scale = 1,
  81.     spread = {x=SPREAD_L, y=SPREAD_L*SQUASH, z=SPREAD_L},
  82.     octaves = 1,
  83.     seed = -8000,
  84.     persist = 0.5
  85. }
  86.  
  87. cavescale.perlin_caves_3_XS = {
  88.     offset = 0,
  89.     scale = 1,
  90.     spread = {x=SPREAD_XS, y=SPREAD_XS*SQUASH, z=SPREAD_XS},
  91.     octaves = 1,
  92.     seed = -9000,
  93.     persist = 0.5
  94. }
  95.  
  96. cavescale.perlin_caves_3_S = {
  97.     offset = 0,
  98.     scale = 1,
  99.     spread = {x=SPREAD_S, y=SPREAD_S*SQUASH, z=SPREAD_S},
  100.     octaves = 1,
  101.     seed = -10000,
  102.     persist = 0.5
  103. }
  104.  
  105. cavescale.perlin_caves_3_M = {
  106.     offset = 0,
  107.     scale = 1,
  108.     spread = {x=SPREAD_M, y=SPREAD_M*SQUASH, z=SPREAD_M},
  109.     octaves = 1,
  110.     seed = -11000,
  111.     persist = 0.5
  112. }
  113.  
  114. cavescale.perlin_caves_3_L = {
  115.     offset = 0,
  116.     scale = 1,
  117.     spread = {x=SPREAD_L, y=SPREAD_L*SQUASH, z=SPREAD_L},
  118.     octaves = 1,
  119.     seed = -12000,
  120.     persist = 0.5
  121. }
  122.  
  123. cavescale.perlin_cavernosity = {
  124.     offset = 0,
  125.     scale = 1,
  126.     spread = {x=SPREAD_GEOLOGY, y=SPREAD_GEOLOGY, z=SPREAD_GEOLOGY},
  127.     octaves = 2,
  128.     seed = -13000,
  129.     persist = 0.5
  130. }
  131.  
  132. minetest.register_on_mapgen_init(function(mgparams)
  133.     if mgparams.mgname ~= "singlenode" then
  134.         print("[cavescale_v2] Set mapgen to singlenode")
  135.         minetest.set_mapgen_params({mgname="singlenode"})
  136.     end
  137. end)
  138.  
  139. minetest.register_on_generated(function(minp, maxp, seed)
  140.  
  141.     local air = minetest.get_content_id("air")
  142.     local grass = minetest.get_content_id("default:dirt_with_grass")
  143.     local dirt = minetest.get_content_id("default:dirt")
  144.     local stone = minetest.get_content_id("default:stone")
  145.    
  146.     local t1 = os.clock()
  147.     local sidelen = maxp.x - minp.x + 1
  148.     local chulens = {x=sidelen, y=sidelen, z=sidelen}
  149.    
  150.     local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
  151.     local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
  152.     local data = vm:get_data()
  153.     local caves_1XS_map = minetest.get_perlin_map(cavescale.perlin_caves_1_XS, chulens):get3dMap_flat(minp)
  154.     local caves_1S_map = minetest.get_perlin_map(cavescale.perlin_caves_1_S, chulens):get3dMap_flat(minp)
  155.     local caves_1M_map = minetest.get_perlin_map(cavescale.perlin_caves_1_M, chulens):get3dMap_flat(minp)
  156.     local caves_1L_map = minetest.get_perlin_map(cavescale.perlin_caves_1_L, chulens):get3dMap_flat(minp)
  157.     local caves_2XS_map = minetest.get_perlin_map(cavescale.perlin_caves_2_XS, chulens):get3dMap_flat(minp)
  158.     local caves_2S_map = minetest.get_perlin_map(cavescale.perlin_caves_2_S, chulens):get3dMap_flat(minp)
  159.     local caves_2M_map = minetest.get_perlin_map(cavescale.perlin_caves_2_M, chulens):get3dMap_flat(minp)
  160.     local caves_2L_map = minetest.get_perlin_map(cavescale.perlin_caves_2_L, chulens):get3dMap_flat(minp)
  161.     local caves_3XS_map = minetest.get_perlin_map(cavescale.perlin_caves_3_XS, chulens):get3dMap_flat(minp)
  162.     local caves_3S_map = minetest.get_perlin_map(cavescale.perlin_caves_3_S, chulens):get3dMap_flat(minp)
  163.     local caves_3M_map = minetest.get_perlin_map(cavescale.perlin_caves_3_M, chulens):get3dMap_flat(minp)
  164.     local caves_3L_map = minetest.get_perlin_map(cavescale.perlin_caves_3_L, chulens):get3dMap_flat(minp)
  165.     local cavernosity_map = minetest.get_perlin_map(cavescale.perlin_cavernosity, chulens):get2dMap_flat({x=minp.x, y=minp.z})
  166.    
  167.     -- fill the floor in with grass/dirt/stone first
  168.     nixyz = 1
  169.     for z=minp.z,maxp.z,1 do
  170.         for y=minp.y,maxp.y,1 do
  171.             for x=minp.x,maxp.x,1 do
  172.                 if y <= -5 then
  173.                     data[area:index(x, y, z)] = stone
  174.                 elseif y <= -2 then
  175.                     data[area:index(x, y, z)] = dirt
  176.                 elseif y <= -1 then
  177.                     data[area:index(x, y, z)] = grass
  178.                 end
  179.                 nixyz = nixyz + 1
  180.             end
  181.         end
  182.     end
  183.    
  184.     nixyz = 1
  185.     nixz = 1
  186.     for z=minp.z,maxp.z,1 do
  187.         for y=minp.y,maxp.y,1 do
  188.             for x=minp.x,maxp.x,1 do
  189.                 -- pull values from all the perlin noise maps
  190.                 local caves_1XS = caves_1XS_map[nixyz]
  191.                 local caves_1S = caves_1S_map[nixyz]
  192.                 local caves_1M = caves_1M_map[nixyz]
  193.                 local caves_1L = caves_1L_map[nixyz]
  194.                 local caves_2XS = caves_2XS_map[nixyz]
  195.                 local caves_2S = caves_2S_map[nixyz]
  196.                 local caves_2M = caves_2M_map[nixyz]
  197.                 local caves_2L = caves_2L_map[nixyz]
  198.                 local caves_3XS = caves_3XS_map[nixyz]
  199.                 local caves_3S = caves_3S_map[nixyz]
  200.                 local caves_3M = caves_3M_map[nixyz]
  201.                 local caves_3L = caves_3L_map[nixyz]
  202.                 local cavernosity = cavernosity_map[nixz]
  203.                 -- make our perlin noise scale with cavernosity near the surface
  204.                 -- low cavernosity means low density cave networks (poorly connected)
  205.                 -- high cavernosity means high density cave networks (well connected)
  206.                 local surface_influence = math.max(1-0.1*math.max((-y)/50,0),0)
  207.                 local spread = math.max(cavernosity,0)*SPREAD_XS + math.max(1-math.abs(cavernosity),0)*SPREAD_S + math.max(-cavernosity,0)*SPREAD_M
  208.                 local threshold = 0.03 * ((32/spread)*surface_influence + 1*(1-surface_influence))
  209.                 local caves_1_surface = math.max(cavernosity,0)*caves_1XS + math.max(1-math.abs(cavernosity),0)*caves_1S + math.max(-cavernosity,0)*caves_1M
  210.                 local caves_2_surface = math.max(cavernosity,0)*caves_2XS + math.max(1-math.abs(cavernosity),0)*caves_2S + math.max(-cavernosity,0)*caves_2M
  211.                 local caves_3_surface = math.max(cavernosity,0)*caves_3XS + math.max(1-math.abs(cavernosity),0)*caves_3S + math.max(-cavernosity,0)*caves_3M
  212.                 -- make our perlin noise scale up with depth
  213.                 -- small caves near the surface - big ones deep down
  214.                 local scale = math.min(0.1*math.max((-y)/100,0),1)
  215.                 local caves_1 = math.max(1-2*scale,0)*caves_1_surface + math.max(1-2*math.abs(scale-0.5),0)*caves_1M + math.max(1-2*(1-scale),0)*caves_1L
  216.                 local caves_2 = math.max(1-2*scale,0)*caves_2_surface + math.max(1-2*math.abs(scale-0.5),0)*caves_2M + math.max(1-2*(1-scale),0)*caves_2L
  217.                 local caves_3 = math.max(1-3*scale,0)*caves_3_surface + math.max(1-3*math.abs(scale-0.5),0)*caves_3M + math.max(1-3*(1-scale),0)*caves_3L
  218.                 local volume_1 = (math.abs(caves_1) < threshold)
  219.                 local volume_2 = (math.abs(caves_2) < threshold)
  220.                 local volume_3 = (math.abs(caves_3) < threshold)
  221.                 local radius = 3
  222.                 if ((volume_1 and volume_2) or (volume_2 and volume_3)) and y < 5 then
  223.                     -- clear out a sphere centred on this node
  224.                     for rz=math.max(z-radius,minp.z),math.min(z+radius,maxp.z),1 do
  225.                         for ry=math.max(y-radius,minp.y),math.min(y+radius,maxp.y),1 do
  226.                             for rx=math.max(x-radius,minp.x),math.min(x+radius,maxp.x),1 do
  227.                                 if ((rx-x)^2+(ry-y)^2+(rz-z)^2) <= radius then
  228.                                     data[area:index(rx, ry, rz)] = air
  229.                                 end
  230.                             end
  231.                         end
  232.                     end
  233.                 end
  234.                 nixyz = nixyz + 1
  235.                 nixz = nixz + 1
  236.             end
  237.             nixz = nixz - sidelen
  238.         end
  239.         nixz = nixz + sidelen
  240.     end
  241.    
  242.     local t2 = os.clock()
  243.     minetest.log("action", minetest.pos_to_string(minp).." generated in "..math.ceil((t2 - t1) * 1000).." ms")
  244.  
  245.     vm:set_data(data)
  246.     vm:set_lighting({day=16, night=0})
  247.     vm:calc_lighting()
  248.     --vm:update_liquids()
  249.     vm:write_to_map(data)
  250. end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement