Set world size in Minetest
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

init.lua 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. --------------
  2. -- TODO: Check for terrain height
  3. -- Defines the edge of a world
  4. local edge = tonumber(minetest.settings:get("world_edge")) or 30000
  5. -- Radius which should be checked for a good teleportation place
  6. local radius = 2
  7. --------------
  8. if minetest.settings:get_bool("log_mods") then
  9. minetest.log("action", "World edge: " .. edge)
  10. end
  11. local count = 0
  12. local waiting_list = {}
  13. --[[ Explanation of waiting_list table
  14. Index = Player name
  15. Value = {
  16. player = Player to teleport
  17. pos = Destination
  18. obj = Attacked entity
  19. notified = When the player must wait longer...
  20. }
  21. ]]
  22. minetest.register_globalstep(function(dtime)
  23. count = count + dtime
  24. if count < 3 then
  25. return
  26. end
  27. count = 0
  28. for k, v in pairs(waiting_list) do
  29. if v.player and v.player:is_player() then
  30. local pos = get_surface_pos(v.pos)
  31. if pos then
  32. v.obj:setpos(pos)
  33. minetest.after(0.2, function(p, o)
  34. p:set_detach()
  35. o:remove()
  36. end, v.player, v.obj)
  37. waiting_list[k] = nil
  38. elseif not v.notified then
  39. v.notified = true
  40. minetest.chat_send_player(k, "Sorry, we have not found a free place yet. Please be patient.")
  41. end
  42. else
  43. v.obj:remove()
  44. waiting_list[k] = nil
  45. end
  46. end
  47. local newedge = edge - 5
  48. -- Check if the players are near the edge and teleport them
  49. local players = minetest.get_connected_players()
  50. for i, player in ipairs(players) do
  51. local name = player:get_player_name()
  52. if not waiting_list[name] then
  53. local pos = vector.round(player:getpos())
  54. local newpos = nil
  55. if pos.x >= edge then
  56. newpos = {x = -newedge, y = 10, z = pos.z}
  57. elseif pos.x <= -edge then
  58. newpos = {x = newedge, y = 10, z = pos.z}
  59. end
  60. if pos.z >= edge then
  61. newpos = {x = pos.x, y = 10, z = -newedge}
  62. elseif pos.z <= -edge then
  63. newpos = {x = pos.x, y = 10, z = newedge}
  64. end
  65. -- Teleport the player
  66. if newpos then
  67. minetest.chat_send_player(name, "Please wait a few seconds. We will teleport you soon.")
  68. local obj = minetest.add_entity(newpos, "worldedge:lock")
  69. player:set_attach(obj, "", {x=0, y=0, z=0}, {x=0, y=0, z=0})
  70. waiting_list[name] = {
  71. player = player,
  72. pos = newpos,
  73. obj = obj
  74. }
  75. obj:setpos(newpos)
  76. end
  77. end
  78. end
  79. end)
  80. function get_surface_pos(pos)
  81. local minp = {
  82. x = pos.x - radius - 1,
  83. y = -10,
  84. z = pos.z - radius - 1
  85. }
  86. local maxp = {
  87. x = pos.x + radius - 1,
  88. y = 50,
  89. z = pos.z + radius - 1
  90. }
  91. local c_air = minetest.get_content_id("air")
  92. local c_ignore = minetest.get_content_id("ignore")
  93. local vm = minetest.get_voxel_manip()
  94. local emin, emax = vm:read_from_map(minp, maxp)
  95. local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
  96. local data = vm:get_data()
  97. local seen_air = false
  98. local deepest_place = vector.new(pos)
  99. deepest_place.y = 50
  100. for x = minp.x, maxp.x do
  101. for z = minp.z, maxp.z do
  102. local solid = 0
  103. for y = deepest_place.y, -10, -1 do
  104. local node = data[area:index(x, y, z)]
  105. if y < deepest_place.y and node == c_air then
  106. deepest_place = vector.new(x, y, z)
  107. seen_air = true
  108. end
  109. if solid > 5 then
  110. -- Do not find caves!
  111. break
  112. end
  113. if node ~= c_air and node ~= c_ignore then
  114. solid = solid + 1
  115. end
  116. end
  117. end
  118. end
  119. if seen_air then
  120. return deepest_place
  121. else
  122. return false
  123. end
  124. end
  125. minetest.register_entity("worldedge:lock", {
  126. initial_properties = {
  127. is_visible = false
  128. },
  129. on_activate = function(staticdata, dtime_s)
  130. --self.object:set_armor_groups({immortal = 1})
  131. end
  132. })
  133. minetest.log("action", "[worldedge] loaded.")