init.lua 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. -- Disable by mapgen, setting or if 'static_spawnpoint' is set
  2. --------------------------------------------------------------
  3. local mg_name = minetest.get_mapgen_setting("mg_name")
  4. if mg_name == "v6" or mg_name == "singlenode" or
  5. minetest.settings:get("static_spawnpoint") or
  6. minetest.settings:get_bool("engine_spawn") then
  7. return
  8. end
  9. -- Parameters
  10. -------------
  11. -- Resolution of search grid in nodes.
  12. local res = 64
  13. -- Number of points checked in the square search grid (edge * edge).
  14. local checks = 128 * 128
  15. -- Starting point for biome checks. This also sets the y co-ordinate for all
  16. -- points checked, so the suitable biomes must be active at this y.
  17. local pos = {x = 0, y = 8, z = 0}
  18. -- Table of suitable biomes
  19. local biome_ids = {
  20. minetest.get_biome_id("taiga"),
  21. minetest.get_biome_id("coniferous_forest"),
  22. minetest.get_biome_id("deciduous_forest"),
  23. minetest.get_biome_id("grassland"),
  24. minetest.get_biome_id("savanna"),
  25. }
  26. -- End of parameters
  27. --------------------
  28. -- Direction table
  29. local dirs = {
  30. {x = 0, y = 0, z = 1},
  31. {x = -1, y = 0, z = 0},
  32. {x = 0, y = 0, z = -1},
  33. {x = 1, y = 0, z = 0},
  34. }
  35. -- Initial variables
  36. local edge_len = 1
  37. local edge_dist = 0
  38. local dir_step = 0
  39. local dir_ind = 1
  40. local searched = false
  41. local success = false
  42. local spawn_pos = {}
  43. --Functions
  44. -----------
  45. -- Get next position on square search spiral
  46. local function next_pos()
  47. if edge_dist == edge_len then
  48. edge_dist = 0
  49. dir_ind = dir_ind + 1
  50. if dir_ind == 5 then
  51. dir_ind = 1
  52. end
  53. dir_step = dir_step + 1
  54. edge_len = math.floor(dir_step / 2) + 1
  55. end
  56. local dir = dirs[dir_ind]
  57. local move = vector.multiply(dir, res)
  58. edge_dist = edge_dist + 1
  59. return vector.add(pos, move)
  60. end
  61. -- Spawn position search
  62. local function search()
  63. for iter = 1, checks do
  64. local biome_data = minetest.get_biome_data(pos)
  65. -- Sometimes biome_data is nil
  66. local biome = biome_data and biome_data.biome
  67. for id_ind = 1, #biome_ids do
  68. local biome_id = biome_ids[id_ind]
  69. if biome == biome_id then
  70. local spawn_y = minetest.get_spawn_level(pos.x, pos.z)
  71. if spawn_y then
  72. spawn_pos = {x = pos.x, y = spawn_y, z = pos.z}
  73. return true
  74. end
  75. end
  76. end
  77. pos = next_pos()
  78. end
  79. return false
  80. end
  81. -- On new player spawn and player respawn
  82. -- Search for spawn position once per server session. If successful, store
  83. -- position and reposition players, otherwise leave them at engine spawn
  84. -- position.
  85. local function on_spawn(player)
  86. if not searched then
  87. success = search()
  88. searched = true
  89. end
  90. if success then
  91. player:set_pos(spawn_pos)
  92. end
  93. end
  94. minetest.register_on_newplayer(function(player)
  95. on_spawn(player)
  96. end)
  97. minetest.register_on_respawnplayer(function(player)
  98. on_spawn(player)
  99. return true
  100. end)