init.lua 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. --[[
  2. ether_lands is a Minetest mod that adds its own floatlands-like map generation
  3. Copyright (C) 2019 Kurtzmusch
  4. This file is part of ether_lands
  5. ether_lands is free software; you can redistribute it and/or modify it under
  6. the terms of the GNU Lesser General Public License as published by the Free
  7. Software Foundation; either version 2.1 of the License, or (at your option) any
  8. later version.
  9. ether_lands is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  11. PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with ether_lands. If not, see <https://www.gnu.org/licenses/>.
  14. --]]
  15. -- based on paramat's mapgen: fracture
  16. -- global tables --------------------------------------------------------------
  17. ether_lands = {} --external exposition of mod's tables and functions
  18. _ether_lands = {} --internal ^
  19. -- terrain parameters ---------------------------------------------------------
  20. local REALM_START = 2000 -- initial height for this realm
  21. local STONE_THRESHOLD = 0.03
  22. local DIRT_THRESHOLD = 0
  23. local HEIGHT_VARIANCE = 800 -- total height variance for the heightmap used to calculate biomes and overall height of layers
  24. local GRASS_FREQUENCY = 0.7
  25. local TREE_FREQUENCY = 0.001
  26. local TREE3_FREQUENCY = 0.1
  27. local CYANLANDS_DISPLACEMENT = 20
  28. local CYANLANDS_LAYER_HEIGHT = 350
  29. local CYANLANDS_BOTTOMGRADIENT_LENGHT = 32
  30. local CYANLANDS_TOPGRADIENT_LENGTH = 250 -- used to ease of the density of the noise as height within the layer increases
  31. local CYANLANDS_TOPGRADIENT_START = CYANLANDS_LAYER_HEIGHT-CYANLANDS_TOPGRADIENT_LENGTH -- height within the layer for the top gradient
  32. local CYANLANDS_HORIZONTAL_UPPERGRADIENT_LENGTH = 40 -- used to ease of the density of the noise in the edge with bluelands
  33. local CYANLANDS_HORIZONTAL_LOWERGRADIENT_LENGTH = 40 -- ^ orangelands
  34. -- TODO _BIOME_HEIGHT should have the same meaning for any biome
  35. local BLUELANDS_DISPLACEMENT = 20
  36. local BLUELANDS_BIOME_HEIGHT = HEIGHT_VARIANCE - 200 -- when the heightmap is above this, the biome is bluelands
  37. local BLUELANDS_LAYER_HEIGHT = 200
  38. local BLUELANDS_BOTTOMGRADIENT_LENGHT = 32
  39. local BLUELANDS_TOPGRADIENT_LENGTH = 100
  40. local BLUELANDS_TOPGRADIENT_START = BLUELANDS_LAYER_HEIGHT-BLUELANDS_TOPGRADIENT_LENGTH
  41. local BLUELANDS_HORIZONTAL_LOWERGRADIENT_LENGTH = 50
  42. local ORANGELANDS_LAYER_HEIGHT = 200
  43. local ORANGELANDS_TOPGRADIENT_LENGTH = 100
  44. local ORANGELANDS_BOTTOMGRADIENT_LENGHT = 32
  45. local ORANGELANDS_TOPGRADIENT_START = ORANGELANDS_LAYER_HEIGHT-ORANGELANDS_TOPGRADIENT_LENGTH
  46. local ORANGELANDS_BIOME_HEIGHT = 250 -- when the heightmap is below this, the biome is orangelands
  47. local ORANGELANDS_HORIZONTAL_UPPERGRADIENT_LENGTH = 50
  48. local REALM_FINISH = REALM_START+HEIGHT_VARIANCE
  49. +CYANLANDS_LAYER_HEIGHT+ORANGELANDS_LAYER_HEIGHT+BLUELANDS_LAYER_HEIGHT
  50. +CYANLANDS_DISPLACEMENT+BLUELANDS_DISPLACEMENT
  51. -- debug stuff
  52. local DEBUG_FLAGS = { debug_blocks=false, overwrite_seed = false, cherrypicked_spawn = false, cherrypick_biome=false, give_privs=false }
  53. local DEBUG_FREQUENCY = 5
  54. local DESIRED_BIOME = "orangelands"
  55. local debug_data = {
  56. mapblock_count = 0,
  57. timeAccumulator_total = 0,
  58. timeAccumulator_getNoise = 0,
  59. timeAccumulator_genIDs = 0,
  60. timeAccumulator_writeVM = 0,
  61. timeAccumulator_writeMap = 0,
  62. timeAccumulator_calcLight = 0,
  63. timeAccumulator_placeSchematics = 0,
  64. }
  65. local schematics_path = minetest.get_modpath("ether_lands").."/schematics/"
  66. ether_lands.schematics = {
  67. path = minetest.get_modpath("ether_lands").."/schematics/",
  68. cyanlands = {
  69. tree1 = schematics_path.."cyanlands_tree1.mts",
  70. tree2 = schematics_path.."cyanlands_tree2.mts",
  71. tree3 = schematics_path.."cyanlands_tree3.mts",
  72. },
  73. orangelands = {
  74. tree1 = schematics_path.."orangelands_tree1.mts",
  75. },
  76. bluelands = {
  77. tree1 = schematics_path.."bluelands_tree1.mts",
  78. },
  79. }
  80. -- noise parameters -----------------------------------------------------------
  81. ether_lands.trees_parameters = {
  82. offset = 0,
  83. scale = 1,
  84. spread = { x = 1200, y = 1200, z = 1200 },
  85. seed = 7,
  86. octaves = 2,
  87. persist = 1,
  88. lacunarity = 16,
  89. }
  90. ether_lands.heightmap_parameters = {
  91. offset = 0,
  92. scale = 1,
  93. spread = { x = 1200, y = 1200, z = 1200 },
  94. seed = 7,
  95. octaves = 1,
  96. persist = 1
  97. }
  98. ether_lands.cyanland_noise1_parameters = {
  99. offset = 0,
  100. scale = 1,
  101. spread = {x=384, y=128, z=384},
  102. seed = 593,
  103. octaves = 5,
  104. persist = 0.67
  105. }
  106. ether_lands.cyanland_noise2_parameters = {
  107. --second noise in golden ratio
  108. offset = 0,
  109. scale = 1,
  110. spread = {x=311, y=104, z=311},
  111. seed = 593,
  112. octaves = 5,
  113. persist = 0.67
  114. }
  115. -- mapgen ---------------------------------------------------------------------
  116. local modpath = minetest.get_modpath("ether_lands")
  117. dofile(modpath .. "/nodes.lua")
  118. local cid_debugnode_mapchunk = minetest.get_content_id("default:meselamp")
  119. local cid_debugnode_edge = minetest.get_content_id("ether_lands:debugnode_edge")
  120. local cid_debugnode_actualedge = minetest.get_content_id("ether_lands:debugnode_actualedge")
  121. local cid_stone_cyan = minetest.get_content_id("ether_lands:levistone_cyan")
  122. local cid_stone_blue = minetest.get_content_id("ether_lands:levistone_blue")
  123. local cid_stone_orange = minetest.get_content_id("ether_lands:levistone_orange")
  124. local cid_grass_cyan = minetest.get_content_id("ether_lands:grass_cyan")
  125. local cid_grass_blue = minetest.get_content_id("ether_lands:grass_blue")
  126. local cid_grass_orange = minetest.get_content_id("ether_lands:grass_orange")
  127. local cid_dirt_cyan = minetest.get_content_id("ether_lands:dirt_cyan")
  128. local cid_dirt_blue = minetest.get_content_id("ether_lands:dirt_blue")
  129. local cid_dirt_orange = minetest.get_content_id("ether_lands:dirt_orange")
  130. local cid_grass1_cyan = minetest.get_content_id("ether_lands:plant_1_grass_cyan")
  131. local cid_grass1_blue = minetest.get_content_id("ether_lands:plant_1_grass_blue")
  132. local cid_grass1_orange = minetest.get_content_id("ether_lands:plant_1_grass_orange")
  133. local cid_air = minetest.get_content_id("air")
  134. local emerged_dimensions
  135. local mapchunk_dimensions
  136. local cid_data
  137. local parama2_data
  138. local cyanland1_values
  139. local cyanland2_values
  140. local heightmap_values
  141. local mapchunk_length -- assumes mapchunks and emerged vmanips are always cubes
  142. local emerged_length
  143. minetest.register_on_mapgen_init( function(mapgen_params)
  144. if( DEBUG_FLAGS.overwrite_seed ) then minetest.set_mapgen_setting("seed", 10100000, true) end
  145. mapchunk_length = minetest.get_mapgen_setting("chunksize")*16 --TODO 16 should not be hard coded
  146. emerged_length = mapchunk_length+(16*2) --TODO figure out if emerged areas is always 1 mapblock bigger in all directions
  147. cid_data = {}
  148. cid_data[emerged_length^3] = cid_air
  149. param2_data = {}
  150. param2_data[emerged_length^3] = 0
  151. -- really hoping these are creating a contiguos array
  152. cyanland1_values = {}
  153. cyanland1_values[mapchunk_length^3] = 0
  154. cyanland2_values = {}
  155. cyanland2_values[mapchunk_length^3] = 0
  156. heightmap_values = {}
  157. heightmap_values[mapchunk_length^2] = 0
  158. end )
  159. -- places schematics directly in the map
  160. -- TODO figure out why placing on vmanip isnt working
  161. _ether_lands.generate_structures =
  162. function( cid_data, generate_VoxelArea, buffer_VoxelArea )
  163. local zmin = generate_VoxelArea.MinEdge.z
  164. local zmax = generate_VoxelArea.MaxEdge.z
  165. local ymin = generate_VoxelArea.MinEdge.y
  166. local ymax = generate_VoxelArea.MaxEdge.y
  167. local xmin = generate_VoxelArea.MinEdge.x
  168. local xmax = generate_VoxelArea.MaxEdge.x
  169. local node_index_in_emerged
  170. local node_index_in_mapchunk
  171. local node_2d_index = 1
  172. for z = zmin, zmax do
  173. for y = ymin, ymax do
  174. for x = xmin, xmax do
  175. local base_height = heightmap_values[node_2d_index] --TODO cache this for every x,z only
  176. base_height = (base_height+1)/2
  177. base_height = base_height * HEIGHT_VARIANCE
  178. local grass_id
  179. local trees_schematics
  180. if ( base_height > ORANGELANDS_BIOME_HEIGHT ) then
  181. grass_id = cid_grass_cyan
  182. trees_schematics = ether_lands.schematics.cyanlands
  183. end
  184. if( base_height > BLUELANDS_BIOME_HEIGHT ) then
  185. grass_id = cid_grass_blue
  186. trees_schematics = ether_lands.schematics.bluelands
  187. end
  188. if( base_height < ORANGELANDS_BIOME_HEIGHT ) then
  189. grass_id = cid_grass_orange
  190. trees_schematics = ether_lands.schematics.orangelands
  191. end
  192. local node_index_in_emerged = buffer_VoxelArea:index(x,y,z)
  193. if( cid_data[node_index_in_emerged] == grass_id ) then
  194. if( math.random() < TREE_FREQUENCY ) then
  195. local index_west = buffer_VoxelArea:index(x-1,y,z)
  196. local index_east = buffer_VoxelArea:index(x+1,y,z)
  197. local index_south = buffer_VoxelArea:index(x,y,z-1)
  198. local index_north = buffer_VoxelArea:index(x,y,z+1)
  199. if (cid_data[index_west] == grass_id
  200. and(cid_data[index_east] == grass_id )
  201. and(cid_data[index_south] == grass_id )
  202. and(cid_data[index_north] == grass_id )
  203. ) then
  204. minetest.place_schematic(
  205. {x=x, y=y, z=z},
  206. trees_schematics.tree1,
  207. "random",
  208. nil,
  209. true,
  210. "place_center_x,place_center_z"
  211. )
  212. end
  213. end
  214. end
  215. end
  216. end
  217. end
  218. end
  219. -- generates an area of the map and feeds the buffers, can be used for the mapgen, finding a spawnpoint or anything
  220. -- that needs to know about the terrain before its been generated
  221. -- the mapgen will call this and give it the voxelmanip buffers
  222. -- noise_buffers must be { heightmap_buffer=buffer, cyanland1_buffer=buffer, cyanland2_buffer=buffer }
  223. -- generate_VoxelArea is the area to be generated,
  224. -- buffer_VoxelArea is the area to be writen too( the sizes will match cid_buffer and param2_buffer), often times it is bigger than the generated area so the indexes are not the same
  225. ether_lands.generate_area =
  226. function( generate_VoxelArea, buffer_VoxelArea, cid_buffer, param2_buffer, noise_buffers, vmanip )
  227. local time_init
  228. local cyanland_noise1_generator = minetest.get_perlin_map(
  229. ether_lands.cyanland_noise1_parameters, generate_VoxelArea:getExtent() )
  230. local cyanland_noise2_generator = minetest.get_perlin_map(
  231. ether_lands.cyanland_noise2_parameters, generate_VoxelArea:getExtent() )
  232. local heightmap_generator = minetest.get_perlin_map(
  233. ether_lands.heightmap_parameters, {x=generate_VoxelArea:getExtent().x, y=generate_VoxelArea:getExtent().z} )
  234. time_init = os.clock()
  235. heightmap_generator:get_2d_map_flat(
  236. {x=generate_VoxelArea.MinEdge.x, y=generate_VoxelArea.MinEdge.z}, noise_buffers.heightmap_buffer )
  237. -- TODO only retrieve 3d noises if this mapchunk overlaps the biome edges
  238. -- otherwise skip get_map, and loops (maybe even return error so calc lighting and writing back can be skept)
  239. cyanland_noise1_generator:get_3d_map_flat(
  240. generate_VoxelArea.MinEdge, noise_buffers.cyanland1_buffer )
  241. cyanland_noise2_generator:get_3d_map_flat(
  242. generate_VoxelArea.MinEdge, noise_buffers.cyanland2_buffer )
  243. time_elapsed = ( os.clock()-time_init )*1000
  244. debug_data.timeAccumulator_getNoise = debug_data.timeAccumulator_getNoise + time_elapsed
  245. time_init = os.clock()
  246. local zmin = generate_VoxelArea.MinEdge.z
  247. local zmax = generate_VoxelArea.MaxEdge.z
  248. local ymin = generate_VoxelArea.MinEdge.y
  249. local ymax = generate_VoxelArea.MaxEdge.y
  250. local xmin = generate_VoxelArea.MinEdge.x
  251. local xmax = generate_VoxelArea.MaxEdge.x
  252. local node_index_in_emerged
  253. local node_index_in_mapchunk
  254. local node_2d_index = 1
  255. local grass_id = cid_grass_cyan
  256. local levistone_id = cid_stone_cyan
  257. local dirt_id = cid_dirt_cyan
  258. local plant1_id = cid_grass1_cyan
  259. for z = zmin, zmax do
  260. for y = ymin, ymax do
  261. for x = xmin, xmax do
  262. -- lots of stuff here can happen once per height
  263. local base_height = noise_buffers.heightmap_buffer[node_2d_index] --TODO cache this for every x,z only
  264. local height
  265. local max_height
  266. local top_gradient_start
  267. local top_gradient_length
  268. local horizontal_gradient
  269. local horizontal_gradient_start
  270. horizontal_gradient = 1
  271. node_2d_index = node_2d_index + 1
  272. base_height = (base_height+1)/2
  273. base_height = base_height * HEIGHT_VARIANCE
  274. height = base_height
  275. height = height + REALM_START
  276. --TODO precalc most of these and add horizontal_uppergradient_start and __lowergradient_start
  277. if( base_height < ORANGELANDS_BIOME_HEIGHT ) then
  278. levistone_id = cid_stone_orange
  279. grass_id = cid_grass_orange
  280. dirt_id = cid_dirt_orange
  281. plant1_id = cid_grass1_orange
  282. max_height = height+ORANGELANDS_LAYER_HEIGHT
  283. bottom_gradient_start = height
  284. bottom_gradient_length = ORANGELANDS_BOTTOMGRADIENT_LENGHT
  285. bottom_gradient_end = bottom_gradient_start + bottom_gradient_length
  286. top_gradient_start = height + ORANGELANDS_TOPGRADIENT_START
  287. top_gradient_length = ORANGELANDS_TOPGRADIENT_LENGTH
  288. horizontal_gradient_start = ORANGELANDS_BIOME_HEIGHT-ORANGELANDS_HORIZONTAL_UPPERGRADIENT_LENGTH
  289. horizontal_gradient = 1
  290. if( base_height > horizontal_gradient_start ) then
  291. horizontal_gradient = (ORANGELANDS_BIOME_HEIGHT-base_height)/ORANGELANDS_HORIZONTAL_UPPERGRADIENT_LENGTH
  292. end
  293. end
  294. if ( base_height > ORANGELANDS_BIOME_HEIGHT ) then
  295. height = height + ORANGELANDS_LAYER_HEIGHT+CYANLANDS_DISPLACEMENT
  296. max_height = height + CYANLANDS_LAYER_HEIGHT
  297. grass_id = cid_grass_cyan
  298. levistone_id = cid_stone_cyan
  299. dirt_id = cid_dirt_cyan
  300. plant1_id = cid_grass1_cyan
  301. bottom_gradient_start = height
  302. bottom_gradient_length = CYANLANDS_BOTTOMGRADIENT_LENGHT
  303. bottom_gradient_end = bottom_gradient_start + bottom_gradient_length
  304. top_gradient_start = height + CYANLANDS_TOPGRADIENT_START
  305. top_gradient_length = CYANLANDS_TOPGRADIENT_LENGTH
  306. horizontal_gradient = 1
  307. if( base_height < ORANGELANDS_BIOME_HEIGHT+CYANLANDS_HORIZONTAL_LOWERGRADIENT_LENGTH ) then
  308. horizontal_gradient_start = ORANGELANDS_BIOME_HEIGHT+CYANLANDS_HORIZONTAL_LOWERGRADIENT_LENGTH
  309. if( base_height < horizontal_gradient_start ) then
  310. horizontal_gradient = (base_height-ORANGELANDS_BIOME_HEIGHT)/CYANLANDS_HORIZONTAL_LOWERGRADIENT_LENGTH
  311. end
  312. elseif( base_height > BLUELANDS_BIOME_HEIGHT-CYANLANDS_HORIZONTAL_UPPERGRADIENT_LENGTH ) then
  313. horizontal_gradient_start = BLUELANDS_BIOME_HEIGHT-CYANLANDS_HORIZONTAL_UPPERGRADIENT_LENGTH
  314. if( base_height > horizontal_gradient_start ) then
  315. horizontal_gradient = (BLUELANDS_BIOME_HEIGHT-base_height)/CYANLANDS_HORIZONTAL_UPPERGRADIENT_LENGTH
  316. end
  317. end
  318. end
  319. if( base_height > BLUELANDS_BIOME_HEIGHT ) then
  320. height = height + CYANLANDS_LAYER_HEIGHT+BLUELANDS_DISPLACEMENT
  321. max_height = height + BLUELANDS_LAYER_HEIGHT
  322. levistone_id = cid_stone_blue
  323. grass_id = cid_grass_blue
  324. dirt_id = cid_dirt_blue
  325. plant1_id = cid_grass1_blue
  326. bottom_gradient_start = height
  327. bottom_gradient_length = BLUELANDS_BOTTOMGRADIENT_LENGHT
  328. bottom_gradient_end = bottom_gradient_start + bottom_gradient_length
  329. top_gradient_start = height + BLUELANDS_TOPGRADIENT_START
  330. top_gradient_length = BLUELANDS_TOPGRADIENT_LENGTH
  331. horizontal_gradient_start = BLUELANDS_BIOME_HEIGHT+BLUELANDS_HORIZONTAL_LOWERGRADIENT_LENGTH
  332. horizontal_gradient = 1
  333. if( base_height < horizontal_gradient_start ) then
  334. horizontal_gradient = (base_height-BLUELANDS_BIOME_HEIGHT)/BLUELANDS_HORIZONTAL_LOWERGRADIENT_LENGTH
  335. end
  336. end
  337. if( (y > height) and (y < max_height) ) then
  338. local node_index_in_mapchunk = generate_VoxelArea:index(x,y,z)
  339. local cyanland1_density = noise_buffers.cyanland1_buffer[node_index_in_mapchunk]
  340. local cyanland2_density = noise_buffers.cyanland2_buffer[node_index_in_mapchunk]
  341. local density = (cyanland1_density + cyanland2_density)/2
  342. local top_gradient = 1
  343. local bottom_gradient = 1
  344. local gradient = horizontal_gradient
  345. if( y>top_gradient_start ) then
  346. top_gradient = (max_height-y)/top_gradient_length
  347. end
  348. if( y<bottom_gradient_end ) then
  349. bottom_gradient = (y-bottom_gradient_start)/bottom_gradient_length
  350. end
  351. -- pick the smaller gradient. assumes bottom and top gradient never overlaps
  352. if( top_gradient < horizontal_gradient ) then gradient = top_gradient end
  353. if( bottom_gradient < horizontal_gradient ) then gradient = bottom_gradient end
  354. density = ( (density+1)*gradient ) -1
  355. if( density > STONE_THRESHOLD) then
  356. node_index_in_emerged = buffer_VoxelArea:index(x, y, z)
  357. cid_buffer[node_index_in_emerged] = levistone_id
  358. elseif( (y > ymin)
  359. and ( density > DIRT_THRESHOLD )
  360. --TODO by checking not air, this allows to dirt to balance above grass
  361. and (cid_buffer[buffer_VoxelArea:index(x, y-1, z)]~=cid_air) ) then --this seems to cause performance issues... maybe accesing array in wrong order takes it away from cpu cache?
  362. -- skiping checks, but still writing to array makes manip time twice as fast
  363. --could be the checks themselves or wrong read order
  364. node_index_in_emerged = buffer_VoxelArea:index(x, y, z)
  365. cid_buffer[node_index_in_emerged] = dirt_id
  366. elseif( ( y > ymin)
  367. and ( (cid_buffer[buffer_VoxelArea:index(x, y-1, z)]==dirt_id )
  368. or (cid_buffer[buffer_VoxelArea:index(x, y-1, z)]==levistone_id) ) ) then
  369. node_index_in_emerged = buffer_VoxelArea:index(x, y, z)
  370. cid_buffer[node_index_in_emerged] = grass_id
  371. elseif( (y > ymin)
  372. and ( cid_buffer[buffer_VoxelArea:index(x, y-1, z)]==grass_id )
  373. and ( math.random() < GRASS_FREQUENCY ) ) then
  374. if( math.fmod(y, 25) == 0) and (math.fmod(x, 25) == 0 ) then
  375. --what is this?
  376. end
  377. node_index_in_emerged = buffer_VoxelArea:index(x, y, z)
  378. cid_buffer[node_index_in_emerged] = plant1_id
  379. local p2 = 8
  380. local r = math.random()
  381. if( r > 0.7 ) then p2 = 10 elseif( r < 0.3 ) then p2 = 40 end
  382. param2_buffer[node_index_in_emerged] = p2
  383. end
  384. end
  385. if( DEBUG_FLAGS.debug_blocks ) then
  386. if (( y == math.floor(height) ) or ( y == math.floor(max_height) ))
  387. then
  388. node_index_in_emerged = buffer_VoxelArea:index(x, y, z)
  389. cid_buffer[node_index_in_emerged] = cid_debugnode_edge
  390. end
  391. local actualedge_min = height
  392. local actualedge_max = top_gradient_start+top_gradient_length*0.5 -- 0.5 is dirt density remaped to [0:1]
  393. if (( y == math.floor(actualedge_min) ) or ( y == math.floor(actualedge_max) ))
  394. then
  395. node_index_in_emerged = buffer_VoxelArea:index(x, y, z)
  396. cid_buffer[node_index_in_emerged] = cid_debugnode_actualedge
  397. end
  398. if (( x == xmin+16*2+8) or ( x == xmin+16*2+1+8 ))
  399. and(( y == ymin+16*2+8) or ( y == ymin+16*2+1+8 ))
  400. and(( z == zmin+16*2+8) or ( z == zmin+16*2+1+8 ))
  401. then
  402. node_index_in_emerged = buffer_VoxelArea:index(x, y, z)
  403. cid_buffer[node_index_in_emerged] = cid_debugnode_mapchunk
  404. end
  405. end
  406. end
  407. node_2d_index = node_2d_index - generate_VoxelArea:getExtent().x
  408. end
  409. node_2d_index = node_2d_index + generate_VoxelArea:getExtent().x
  410. end
  411. time_elapsed = ( os.clock()-time_init )*1000
  412. debug_data.timeAccumulator_genIDs = debug_data.timeAccumulator_genIDs + time_elapsed
  413. end
  414. local debug_timer = 0
  415. _ether_lands.on_globalstep = function( delta_time )
  416. debug_timer = debug_timer + delta_time
  417. if( debug_timer >= DEBUG_FREQUENCY ) then
  418. minetest.log("warning", "----timers-------------------------------------------------------------" )
  419. minetest.log("warning", "avg total time: "..math.ceil( debug_data.timeAccumulator_total/debug_data.mapblock_count).."ms" )
  420. minetest.log("warning", "avg get noise values: "..math.ceil( debug_data.timeAccumulator_getNoise/debug_data.mapblock_count).."ms" )
  421. minetest.log("warning", "avg manipulate mapchunk data: "..math.ceil( debug_data.timeAccumulator_genIDs/debug_data.mapblock_count).."ms" )
  422. minetest.log("warning", "avg write to vm: "..math.ceil( debug_data.timeAccumulator_writeVM/debug_data.mapblock_count).."ms" )
  423. minetest.log("warning", "avg write to map: "..math.ceil(debug_data.timeAccumulator_writeMap/debug_data.mapblock_count).."ms" )
  424. minetest.log("warning", "avg place schematics: "..math.ceil(debug_data.timeAccumulator_placeSchematics/debug_data.mapblock_count).."ms" )
  425. minetest.log( "warning", "memory: " .. math.ceil(collectgarbage("count")/1024) )
  426. minetest.log("warning", "-----------------------------------------------------------------------" )
  427. debug_timer = 0
  428. end
  429. end
  430. _ether_lands.on_generated = function( min_mapchunk_position, max_mapchunk_position, seed )
  431. if( min_mapchunk_position.y > REALM_FINISH ) then return end
  432. if( max_mapchunk_position.y < REALM_START ) then return end
  433. debug_data.mapblock_count = debug_data.mapblock_count + 1
  434. local time_total_init = os.clock()
  435. local time_total_elapsed
  436. --this is done here because afaik there is no way to get mapchunk dimensions elsewhere
  437. -- try to get smaller voxelmanips since we dont care whatever coremapgen is doing
  438. local voxelmanip, min_emerged_position, max_emerged_position = minetest.get_mapgen_object("voxelmanip")
  439. min_mapchunk_position.y = min_mapchunk_position.y - 8 --generate area that is bigger in -y direction to avoid discontinuities due to dirt requiring stone support
  440. local mapchunk_area = VoxelArea:new{MinEdge=min_mapchunk_position, MaxEdge=max_mapchunk_position}
  441. local emerged_area = VoxelArea:new{MinEdge=min_emerged_position, MaxEdge=max_emerged_position}
  442. voxelmanip:get_data(cid_data)
  443. voxelmanip:get_param2_data(param2_data)
  444. ether_lands.generate_area( mapchunk_area, emerged_area, cid_data, param2_data,
  445. { heightmap_buffer=heightmap_values, cyanland1_buffer=cyanland1_values, cyanland2_buffer=cyanland2_values }, voxelmanip )
  446. local time_writeToVM_init = os.clock()
  447. local time_writeToVM_elapsed
  448. voxelmanip:set_data(cid_data)
  449. voxelmanip:set_param2_data(param2_data)
  450. voxelmanip:set_lighting( {day=9, night=0} )
  451. voxelmanip:calc_lighting()
  452. time_writeToVM_elapsed = (os.clock()-time_writeToVM_init)*1000
  453. debug_data.timeAccumulator_writeVM = debug_data.timeAccumulator_writeVM + time_writeToVM_elapsed
  454. local time_writeToMap_init = os.clock()
  455. local time_writeToMap_elapsed
  456. voxelmanip:write_to_map()
  457. time_writeToMap_elapsed = (os.clock()-time_writeToMap_init)*1000
  458. debug_data.timeAccumulator_writeMap = debug_data.timeAccumulator_writeMap + time_writeToMap_elapsed
  459. local time_placeSchematics_init = os.clock()
  460. local time_placeSchematics_elapsed
  461. _ether_lands.generate_structures( cid_data, mapchunk_area, emerged_area )
  462. time_placeSchematics_elapsed = (os.clock()-time_placeSchematics_init)*1000
  463. debug_data.timeAccumulator_placeSchematics = debug_data.timeAccumulator_placeSchematics + time_placeSchematics_elapsed
  464. time_total_elapsed = (os.clock()-time_total_init)*1000
  465. debug_data.timeAccumulator_total = debug_data.timeAccumulator_total + time_total_elapsed
  466. end
  467. local function find_spawn()
  468. for gx = -20000, 20000, 1000 do
  469. for gz = -20000, 20000, 1000 do
  470. minetest.log("warning", "trying to find spawn at x: ".. gx .. " z: " ..gz)
  471. local ymax = REALM_FINISH
  472. local ymin = REALM_START
  473. local gen_area = VoxelArea:new{ MinEdge={ x=gx, y=ymin, z=gz }, MaxEdge={ x=gx+1, y=ymax, z=gz+1} } -- it seems the perling generators cant handle a 1x1 column TODO report issue on this
  474. local cid_buffer = {}
  475. cid_buffer[gen_area:getVolume()] = 0
  476. for i = 1, gen_area:getVolume() do
  477. cid_buffer[i] = cid_air
  478. end
  479. local param2_buffer = {}
  480. param2_buffer[gen_area:getVolume()] = 0
  481. local h_values = {}
  482. h_values[4] = 0
  483. local c1_values = {}
  484. c1_values[gen_area:getVolume()] = 0
  485. local c2_values = {}
  486. c2_values[gen_area:getVolume()] = 0
  487. ether_lands.generate_area( gen_area, gen_area, cid_buffer, param2_buffer,
  488. { heightmap_buffer=h_values, cyanland1_buffer=c1_values, cyanland2_buffer=c2_values } )
  489. local current_biome
  490. local skip=false
  491. local height = (h_values[1]+1)/2
  492. height = height*HEIGHT_VARIANCE
  493. if( DEBUG_FLAGS.cherrypick_biome ) then
  494. if( height < BLUELANDS_BIOME_HEIGHT ) then current_biome = "cyanlands" end
  495. if( height < ORANGELANDS_BIOME_HEIGHT ) then current_biome = "orangelands" end
  496. if( height > BLUELANDS_BIOME_HEIGHT ) then current_biome = "bluelands" end
  497. if( current_biome~=DESIRED_BIOME ) then skip=true end
  498. end
  499. if not skip then
  500. for y = ymax-1, ymin, -1 do
  501. local i = gen_area:index( gx, y, gz )
  502. local iabove = gen_area:index( gx, y+1, gz)
  503. local ibelow = gen_area:index( gx, y-1, gz)
  504. -- yikes
  505. if( ( (cid_buffer[i] == cid_air)
  506. or (cid_buffer[i] == cid_grass1_cyan)
  507. or (cid_buffer[i] == cid_grass1_orange)
  508. or (cid_buffer[i] == cid_grass1_blue) )
  509. and( cid_buffer[iabove] == cid_air)
  510. and( ( cid_buffer[ibelow] == cid_grass_cyan )
  511. or (cid_buffer[ibelow]==cid_grass_orange)
  512. or (cid_buffer[ibelow]==cid_grass_blue) ) )
  513. then
  514. return {x=gx, y=y, z=gz}
  515. end
  516. end
  517. end
  518. end
  519. end
  520. return {x=0,y=0,z=0}
  521. end
  522. minetest.register_on_joinplayer( function( player )
  523. minetest.set_timeofday(8/24)
  524. if( DEBUG_FLAGS.cherrypicked_spawn ) then player:set_pos({x=510,y=656, z=4850})
  525. else
  526. player:set_pos(find_spawn())
  527. end
  528. player:set_sky( {a=1,r=240,g=240,b=230}, "plain", false )
  529. player:set_physics_override( { speed=2} )
  530. if( DEBUG_FLAGS.give_privs ) then
  531. minetest.set_player_privs("singleplayer", {fly=true,noclip=true,fast=true, settime=true})
  532. end
  533. end )
  534. minetest.register_globalstep( _ether_lands.on_globalstep )
  535. minetest.register_on_generated( _ether_lands.on_generated )