mapgen_nobiomes.lua 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. --[[
  2. Nether mod for minetest
  3. Copyright (C) 2013 PilzAdam
  4. Permission to use, copy, modify, and/or distribute this software for
  5. any purpose with or without fee is hereby granted, provided that the
  6. above copyright notice and this permission notice appear in all copies.
  7. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  8. WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  9. WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
  10. BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
  11. OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  12. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  13. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  14. SOFTWARE.
  15. ]]--
  16. -- Parameters
  17. local NETHER_CEILING = nether.DEPTH_CEILING
  18. local NETHER_FLOOR = nether.DEPTH_FLOOR
  19. local TCAVE = 0.6
  20. local BLEND = 128
  21. -- 3D noise
  22. local np_cave = {
  23. offset = 0,
  24. scale = 1,
  25. spread = {x = 384, y = 128, z = 384}, -- squashed 3:1
  26. seed = 59033,
  27. octaves = 5,
  28. persist = 0.7,
  29. lacunarity = 2.0,
  30. --flags = ""
  31. }
  32. -- Stuff
  33. local yblmin = NETHER_FLOOR + BLEND * 2
  34. local yblmax = NETHER_CEILING - BLEND * 2
  35. -- Mapgen
  36. dofile(nether.path .. "/mapgen_decorations.lua")
  37. -- Initialize noise object, localise noise and data buffers
  38. local nobj_cave = nil
  39. local nbuf_cave = nil
  40. local dbuf = nil
  41. -- Content ids
  42. local c_air = minetest.get_content_id("air")
  43. --local c_stone_with_coal = minetest.get_content_id("default:stone_with_coal")
  44. --local c_stone_with_iron = minetest.get_content_id("default:stone_with_iron")
  45. local c_stone_with_mese = minetest.get_content_id("default:stone_with_mese")
  46. local c_stone_with_diamond = minetest.get_content_id("default:stone_with_diamond")
  47. local c_stone_with_gold = minetest.get_content_id("default:stone_with_gold")
  48. --local c_stone_with_copper = minetest.get_content_id("default:stone_with_copper")
  49. local c_mese = minetest.get_content_id("default:mese")
  50. local c_gravel = minetest.get_content_id("default:gravel")
  51. local c_dirt = minetest.get_content_id("default:dirt")
  52. local c_sand = minetest.get_content_id("default:sand")
  53. local c_cobble = minetest.get_content_id("default:cobble")
  54. local c_mossycobble = minetest.get_content_id("default:mossycobble")
  55. local c_stair_cobble = minetest.get_content_id("stairs:stair_cobble")
  56. local c_lava_source = minetest.get_content_id("default:lava_source")
  57. local c_lava_flowing = minetest.get_content_id("default:lava_flowing")
  58. local c_water_source = minetest.get_content_id("default:water_source")
  59. local c_water_flowing = minetest.get_content_id("default:water_flowing")
  60. local c_glowstone = minetest.get_content_id("nether:glowstone")
  61. local c_nethersand = minetest.get_content_id("nether:sand")
  62. local c_netherbrick = minetest.get_content_id("nether:brick")
  63. local c_netherrack = minetest.get_content_id("nether:rack")
  64. -- On-generated function
  65. minetest.register_on_generated(function(minp, maxp, seed)
  66. if minp.y > NETHER_CEILING or maxp.y < NETHER_FLOOR then
  67. return
  68. end
  69. local x1 = maxp.x
  70. local y1 = math.min(maxp.y, NETHER_CEILING)
  71. local z1 = maxp.z
  72. local x0 = minp.x
  73. local y0 = math.max(minp.y, NETHER_FLOOR)
  74. local z0 = minp.z
  75. local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
  76. local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
  77. local data = vm:get_data(dbuf)
  78. local x11 = emax.x -- Limits of mapchunk plus mapblock shell
  79. local y11 = emax.y
  80. local z11 = emax.z
  81. local x00 = emin.x
  82. local y00 = emin.y
  83. local z00 = emin.z
  84. local ystride = x1 - x0 + 1
  85. local zstride = ystride * ystride
  86. local chulens = {x = ystride, y = ystride, z = ystride}
  87. local minposxyz = {x = x0, y = y0, z = z0}
  88. nobj_cave = nobj_cave or minetest.get_perlin_map(np_cave, chulens)
  89. local nvals_cave = nobj_cave:get3dMap_flat(minposxyz, nbuf_cave)
  90. for y = y00, y11 do -- Y loop first to minimise tcave calculations
  91. local tcave
  92. local in_chunk_y = false
  93. if y >= y0 and y <= y1 then
  94. tcave = TCAVE
  95. if y > yblmax then tcave = TCAVE + ((y - yblmax) / BLEND) ^ 2 end
  96. if y < yblmin then tcave = TCAVE + ((yblmin - y) / BLEND) ^ 2 end
  97. in_chunk_y = true
  98. end
  99. for z = z00, z11 do
  100. local vi = area:index(x00, y, z) -- Initial voxelmanip index
  101. local ni
  102. local in_chunk_yz = in_chunk_y and z >= z0 and z <= z1
  103. for x = x00, x11 do
  104. if in_chunk_yz and x == x0 then
  105. -- Initial noisemap index
  106. ni = (z - z0) * zstride + (y - y0) * ystride + 1
  107. end
  108. local in_chunk_yzx = in_chunk_yz and x >= x0 and x <= x1 -- In mapchunk
  109. local id = data[vi] -- Existing node
  110. -- Cave air, cave liquids and dungeons are overgenerated,
  111. -- convert these throughout mapchunk plus shell
  112. if id == c_air or -- Air and liquids to air
  113. id == c_lava_source or
  114. id == c_lava_flowing or
  115. id == c_water_source or
  116. id == c_water_flowing then
  117. data[vi] = c_air
  118. -- Dungeons are preserved so we don't need
  119. -- to check for cavern in the shell
  120. elseif id == c_cobble or -- Dungeons (preserved) to netherbrick
  121. id == c_mossycobble or
  122. id == c_stair_cobble then
  123. data[vi] = c_netherbrick
  124. end
  125. if in_chunk_yzx then -- In mapchunk
  126. if nvals_cave[ni] > tcave then -- Only excavate cavern in mapchunk
  127. data[vi] = c_air
  128. elseif id == c_mese then -- Mese block to lava
  129. data[vi] = c_lava_source
  130. elseif id == c_stone_with_gold or -- Precious ores to glowstone
  131. id == c_stone_with_mese or
  132. id == c_stone_with_diamond then
  133. data[vi] = c_glowstone
  134. elseif id == c_gravel or -- Blob ore to nethersand
  135. id == c_dirt or
  136. id == c_sand then
  137. data[vi] = c_nethersand
  138. else -- All else to netherstone
  139. data[vi] = c_netherrack
  140. end
  141. ni = ni + 1 -- Only increment noise index in mapchunk
  142. end
  143. vi = vi + 1
  144. end
  145. end
  146. end
  147. vm:set_data(data)
  148. -- avoid generating decorations on the underside of the bottom of the nether
  149. if minp.y > NETHER_FLOOR and maxp.y < NETHER_CEILING then minetest.generate_decorations(vm) end
  150. vm:set_lighting({day = 0, night = 0}, minp, maxp)
  151. vm:calc_lighting()
  152. vm:update_liquids()
  153. vm:write_to_map()
  154. end)
  155. -- use knowledge of the nether mapgen algorithm to return a suitable ground level for placing a portal.
  156. function nether.find_nether_ground_y(target_x, target_z, start_y)
  157. local nobj_cave_point = minetest.get_perlin(np_cave)
  158. local air = 0 -- Consecutive air nodes found
  159. for y = start_y, start_y - 4096, -1 do
  160. local nval_cave = nobj_cave_point:get3d({x = target_x, y = y, z = target_z})
  161. if nval_cave > TCAVE then -- Cavern
  162. air = air + 1
  163. else -- Not cavern, check if 4 nodes of space above
  164. if air >= 4 then
  165. -- Check volume for non-natural nodes
  166. local minp = {x = target_x - 1, y = y , z = target_z - 2}
  167. local maxp = {x = target_x + 2, y = y + 4, z = target_z + 2}
  168. if nether.volume_is_natural(minp, maxp) then
  169. return y + 1
  170. else -- Restart search a little lower
  171. nether.find_nether_ground_y(target_x, target_z, y - 16)
  172. end
  173. else -- Not enough space, reset air to zero
  174. air = 0
  175. end
  176. end
  177. end
  178. return start_y -- Fallback
  179. end