init.lua 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. randspawn = randspawn or {}
  2. randspawn.modpath = minetest.get_modpath("randspawn")
  3. -- After the Outback gateway exit coordinates are changed, this is the min and
  4. -- max number of days until it changes again.
  5. randspawn.min_days = 10
  6. randspawn.max_days = 90
  7. function randspawn.check_spawn_reset()
  8. local meta = randspawn.modstorage
  9. local stime = meta:get_string("spawn_reset_timer")
  10. -- If timestamp is missing, then initialize it.
  11. -- Outback reset will be schedualed after the timeout.
  12. if not stime or stime == "" then
  13. local time = os.time()
  14. local days = 60*60*24*math.random(randspawn.min_days, randspawn.max_days)
  15. time = time + days
  16. stime = tostring(time)
  17. meta:set_string("spawn_reset_timer", stime)
  18. -- Find a new spawn point.
  19. randspawn.find_new_spawn()
  20. return
  21. end
  22. local now = os.time()
  23. local later = tonumber(stime) -- Time of future reset (or initialization).
  24. if now >= later then
  25. later = later + 60*60*24*math.random(randspawn.min_days, randspawn.max_days)
  26. stime = tostring(later)
  27. meta:set_string("spawn_reset_timer", stime)
  28. -- Find a new spawn point.
  29. randspawn.find_new_spawn()
  30. end
  31. end
  32. minetest.after(0, function() randspawn.check_spawn_reset() end)
  33. -- Used by the calendar item.
  34. function randspawn.get_spawn_reset_timeout()
  35. local meta = randspawn.modstorage
  36. local stime = meta:get_string("spawn_reset_timer")
  37. local later = tonumber(stime)
  38. local now = os.time()
  39. local diff = later - now
  40. if diff < 0 then diff = 0 end
  41. return diff
  42. end
  43. local function callback(blockpos, action, calls_remaining, param)
  44. -- We don't do anything until the last callback.
  45. if calls_remaining ~= 0 then
  46. return
  47. end
  48. -- Check if there was an error on the LAST call.
  49. -- Note: this will usually fail if the area to emerge intersects the map edge.
  50. -- But usually we don't try to do that, here.
  51. if action == core.EMERGE_CANCELLED or action == core.EMERGE_ERRORED then
  52. return
  53. end
  54. local pos = param.pos
  55. -- Start at sea level and check upwards 200 meters to find ground.
  56. for y = -10, 200, 1 do
  57. pos.y = y
  58. local nu = minetest.get_node(pos)
  59. pos.y = y + 1
  60. local na = minetest.get_node(pos)
  61. -- Exit if map not loaded.
  62. if nu.name == "ignore" or na.name == "ignore" then
  63. break
  64. end
  65. if na.name == "air" and (nu.name == "default:snow" or nu.name == "default:ice") then
  66. pos.y = pos.y + 1
  67. serveressentials.update_exit_location(pos)
  68. return
  69. end
  70. end
  71. -- We didn't find a suitable spawn location. Try again shortly.
  72. minetest.after(60, function() randspawn.find_new_spawn() end)
  73. end
  74. function randspawn.find_new_spawn()
  75. -- Call `serveressentials.update_exit_location()` once we have a new spawnpoint.
  76. local pos = {x=math.random(-6000, 6000), y=0, z=math.random(-6000, 6000)}
  77. local minp = vector.add(pos, {x=-7, y=-7, z=-7})
  78. local maxp = vector.add(pos, {x=7, y=200, z=7})
  79. minetest.emerge_area(minp, maxp, callback, {pos=table.copy(pos)})
  80. end
  81. -- This function shall ALWAYS return the Outback's static_spawn!
  82. local function get_respawn_position(invoke_pos, pname)
  83. -- Regardless of where player dies, if they have no bed,
  84. -- then they respawn in the outback. Note that a player may lose their bed if
  85. -- killed by another player outside of the city.
  86. return rc.static_spawn("abyss")
  87. end
  88. randspawn.get_respawn_pos = get_respawn_position
  89. -- Note: this is also called from the /spawn chatcommand,
  90. -- but only after validation passes (distance, etc.).
  91. -- This API shall place player at the Outback's static_spawn, ALWAYS.
  92. randspawn.reposition_player = function(pname, death_pos)
  93. local player = minetest.get_player_by_name(pname)
  94. if player then
  95. -- Ensure teleport is forced, to prevent a cheat.
  96. local pos = get_respawn_position(death_pos, pname)
  97. pos = vector.add(pos, {x=math.random(-2, 2), y=0, z=math.random(-2, 2)})
  98. preload_tp.preload_and_teleport(pname, pos, 32, nil,
  99. function()
  100. ambiance.sound_play("respawn", pos, 0.5, 10)
  101. end, nil, true)
  102. end
  103. end
  104. -- The calendar item calls this to report the location of the current spawnpoint.
  105. function randspawn.get_spawn_name()
  106. local s = serveressentials.get_current_exit_location()
  107. local p = minetest.string_to_pos(s)
  108. if p then
  109. return rc.pos_to_namestr(p)
  110. end
  111. return "Unknown Location"
  112. end
  113. if not randspawn.run_once then
  114. -- Reloadable.
  115. local file = randspawn.modpath .. "/init.lua"
  116. local name = "randspawn:core"
  117. reload.register_file(name, file, false)
  118. randspawn.modstorage = minetest.get_mod_storage()
  119. randspawn.run_once = true
  120. end