teleport.lua 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. -- Localize for performance.
  2. local vector_round = vector.round
  3. local function realm_to_actual(name)
  4. name = name:lower()
  5. for k, v in ipairs(rc.realms) do
  6. local desc = v.description:lower()
  7. if v.name == name or desc == name then
  8. return v.name
  9. end
  10. end
  11. return name
  12. end
  13. function serveressentials.do_teleport(name, param)
  14. name = name:trim()
  15. param = param:trim()
  16. -- Returns (pos, true) if found, otherwise (pos, false)
  17. local function find_free_position_near(pos)
  18. pos = vector_round(pos)
  19. local tries = {
  20. {x=1,y=0,z=0},
  21. {x=-1,y=0,z=0},
  22. {x=0,y=0,z=1},
  23. {x=0,y=0,z=-1},
  24. }
  25. for _, d in ipairs(tries) do
  26. local p = {x = pos.x+d.x, y = pos.y+d.y, z = pos.z+d.z}
  27. local n = core.get_node_or_nil(p)
  28. if n and n.name then
  29. local def = core.registered_nodes[n.name]
  30. if def and not def.walkable then
  31. if rc.is_valid_realm_pos(p) then
  32. return p, true
  33. end
  34. end
  35. end
  36. end
  37. return pos, false
  38. end
  39. -- Teleport player some distance in a cardinal direction.
  40. local teleportee = nil
  41. local distance = nil
  42. local direction = nil
  43. direction, distance = string.match(param, "^([^ ]+) *: *([%d]+)$")
  44. distance = tonumber(distance)
  45. if direction and distance then
  46. teleportee = minetest.get_player_by_name(name)
  47. if teleportee then
  48. local pname = teleportee:get_player_name()
  49. if default.player_attached[pname] or teleportee:get_attach() then
  50. return false, "Cannot teleport attached player."
  51. end
  52. distance = math.floor(distance)
  53. local havedir = false
  54. local pos = vector.round(teleportee:get_pos())
  55. if direction == "north" or direction == "n" then
  56. pos.z = pos.z + distance
  57. havedir = true
  58. elseif direction == "south" or direction == "s" then
  59. pos.z = pos.z - distance
  60. havedir = true
  61. elseif direction == "west" or direction == "w" then
  62. pos.x = pos.x - distance
  63. havedir = true
  64. elseif direction == "east" or direction == "e" then
  65. pos.x = pos.x + distance
  66. havedir = true
  67. elseif direction == "up" or direction == "u" then
  68. pos.y = pos.y + distance
  69. havedir = true
  70. elseif direction == "down" or direction == "d" then
  71. pos.y = pos.y - distance
  72. havedir = true
  73. end
  74. if havedir then
  75. if not rc.is_valid_realm_pos(pos) then
  76. return false, "Cannot teleport outside of any realm."
  77. end
  78. rc.notify_realm_update(pname, pos)
  79. jail.discharge_pref(teleportee)
  80. teleportee:set_pos(pos)
  81. return true, "Teleporting " .. distance .. " meters " .. direction .. "."
  82. end
  83. end
  84. end
  85. -- Teleport player to absolute coordinates.
  86. local teleportee = nil
  87. local p = {}
  88. p.x, p.y, p.z = string.match(param, "^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
  89. p.x = tonumber(p.x)
  90. p.y = tonumber(p.y)
  91. p.z = tonumber(p.z)
  92. if p.x and p.y and p.z then
  93. p = vector_round(p)
  94. local lm = 31000
  95. if p.x < -lm or p.x > lm or p.y < -lm or p.y > lm or p.z < -lm or p.z > lm then
  96. return false, "Cannot teleport out of map bounds."
  97. end
  98. if not rc.is_valid_realm_pos(p) then
  99. return false, "Cannot teleport outside of any realm."
  100. end
  101. teleportee = core.get_player_by_name(name)
  102. if teleportee then
  103. if default.player_attached[teleportee:get_player_name()] or teleportee:get_attach() then
  104. return false, "Cannot teleport attached player."
  105. end
  106. local o = vector_round(teleportee:get_pos())
  107. rc.notify_realm_update(teleportee:get_player_name(), p)
  108. jail.discharge_pref(teleportee)
  109. teleportee:set_pos(p)
  110. return true, "Teleporting from " .. rc.pos_to_namestr(o) .. " to " .. core.pos_to_string(p) .. ", which is @ " .. rc.pos_to_namestr(p) .. "."
  111. end
  112. end
  113. -- Teleport player to relative realm coordinates.
  114. local teleportee = nil
  115. local p = {}
  116. local realm = nil
  117. --minetest.chat_send_player(name, param)
  118. realm, p.x, p.y, p.z = string.match(param, "^([^ ]+) *: *([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
  119. p.x = tonumber(p.x)
  120. p.y = tonumber(p.y)
  121. p.z = tonumber(p.z)
  122. --minetest.chat_send_player(name, "Got: " .. realm .. ":" .. p.x .. "," .. p.y .. "," .. p.z)
  123. if realm and p.x and p.y and p.z then
  124. p = rc.realmpos_to_pos(realm_to_actual(realm), p)
  125. if not p then
  126. return false, "Cannot interpret realm coordinates."
  127. end
  128. local lm = 31000
  129. if p.x < -lm or p.x > lm or p.y < -lm or p.y > lm or p.z < -lm or p.z > lm then
  130. return false, "Cannot teleport out of map bounds."
  131. end
  132. if not rc.is_valid_realm_pos(p) then
  133. return false, "Cannot teleport outside of any realm."
  134. end
  135. teleportee = core.get_player_by_name(name)
  136. if teleportee then
  137. if default.player_attached[teleportee:get_player_name()] or teleportee:get_attach() then
  138. return false, "Cannot teleport attached player."
  139. end
  140. local o = vector_round(teleportee:get_pos())
  141. rc.notify_realm_update(teleportee:get_player_name(), p)
  142. jail.discharge_pref(teleportee)
  143. teleportee:set_pos(p)
  144. return true, "Teleporting from " .. rc.pos_to_namestr(o) .. " to " .. rc.pos_to_namestr(p) .. "."
  145. end
  146. end
  147. -- Teleport self to target player.
  148. local teleportee = nil
  149. local p = nil
  150. local target_name = nil
  151. target_name = param:match("^([^ ]+)$")
  152. teleportee = core.get_player_by_name(name)
  153. if target_name then
  154. local target = core.get_player_by_name(target_name)
  155. if target then
  156. p = vector_round(target:get_pos())
  157. end
  158. end
  159. if teleportee and p then
  160. p = find_free_position_near(p)
  161. if not rc.is_valid_realm_pos(p) then
  162. return false, "Cannot teleport outside of any realm."
  163. end
  164. if default.player_attached[teleportee:get_player_name()] or teleportee:get_attach() then
  165. return false, "Cannot teleport attached player."
  166. end
  167. local o = vector_round(teleportee:get_pos())
  168. rc.notify_realm_update(teleportee:get_player_name(), p)
  169. jail.discharge_pref(teleportee)
  170. teleportee:set_pos(p)
  171. return true, "Teleporting from " .. rc.pos_to_namestr(o) .. " to <" .. rename.gpn(target_name) .. "> at " .. rc.pos_to_namestr(p) .. "."
  172. end
  173. if not core.check_player_privs(name, {bring=true}) then
  174. return false, "You don't have permission to teleport other players (missing bring privilege)."
  175. end
  176. -- Teleport target player to target coordinates.
  177. local teleportee = nil
  178. local p = {}
  179. local teleportee_name = nil
  180. teleportee_name, p.x, p.y, p.z = param:match("^([^ ]+) +([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
  181. p.x, p.y, p.z = tonumber(p.x), tonumber(p.y), tonumber(p.z)
  182. if teleportee_name then
  183. teleportee = core.get_player_by_name(teleportee_name)
  184. end
  185. if teleportee and p.x and p.y and p.z then
  186. p = vector_round(p)
  187. if not rc.is_valid_realm_pos(p) then
  188. return false, "Cannot teleport players outside realm boundaries."
  189. end
  190. if default.player_attached[teleportee:get_player_name()] or teleportee:get_attach() then
  191. return false, "Cannot teleport attached player."
  192. end
  193. local o = vector_round(teleportee:get_pos())
  194. rc.notify_realm_update(teleportee:get_player_name(), p)
  195. jail.discharge_pref(teleportee)
  196. teleportee:set_pos(p)
  197. return true, "Teleporting <" .. rename.gpn(teleportee_name) .. "> from " .. rc.pos_to_namestr(o) .. " to " .. core.pos_to_string(p) .. ", which is @ " .. rc.pos_to_namestr(p) .. "."
  198. end
  199. -- Teleport target player to realm relative coordinates.
  200. local teleportee = nil
  201. local p = {}
  202. local teleportee_name = nil
  203. local realm = nil
  204. teleportee_name, realm, p.x, p.y, p.z = param:match("^([^ ]+) +([^ ]+) *: *([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
  205. p.x, p.y, p.z = tonumber(p.x), tonumber(p.y), tonumber(p.z)
  206. if teleportee_name then
  207. teleportee = core.get_player_by_name(teleportee_name)
  208. end
  209. if teleportee and realm and p.x and p.y and p.z then
  210. p = rc.realmpos_to_pos(realm_to_actual(realm), p)
  211. if not p then
  212. return false, "Cannot interpret realm coordinates."
  213. end
  214. if not rc.is_valid_realm_pos(p) then
  215. return false, "Cannot teleport players outside realm boundaries."
  216. end
  217. if default.player_attached[teleportee:get_player_name()] or teleportee:get_attach() then
  218. return false, "Cannot teleport attached player."
  219. end
  220. local o = vector_round(teleportee:get_pos())
  221. rc.notify_realm_update(teleportee:get_player_name(), p)
  222. jail.discharge_pref(teleportee)
  223. teleportee:set_pos(p)
  224. return true, "Teleporting <" .. rename.gpn(teleportee_name) .. "> from " .. rc.pos_to_namestr(o) .. " to " .. rc.pos_to_namestr(p) .. "."
  225. end
  226. -- Teleport player to another player.
  227. local teleportee = nil
  228. local p = nil
  229. local teleportee_name = nil
  230. local target_name = nil
  231. teleportee_name, target_name = string.match(param, "^([^ ]+) +([^ ]+)$")
  232. if teleportee_name then
  233. teleportee = core.get_player_by_name(teleportee_name)
  234. end
  235. if target_name then
  236. local target = core.get_player_by_name(target_name)
  237. if target then
  238. p = target:get_pos()
  239. end
  240. end
  241. if teleportee and p then
  242. p = vector_round(p)
  243. if not rc.is_valid_realm_pos(p) then
  244. return false, "Cannot teleport players outside realm boundaries."
  245. end
  246. if default.player_attached[teleportee:get_player_name()] or teleportee:get_attach() then
  247. return false, "Cannot teleport attached player."
  248. end
  249. p = find_free_position_near(p)
  250. local o = vector_round(teleportee:get_pos())
  251. rc.notify_realm_update(teleportee:get_player_name(), p)
  252. jail.discharge_pref(teleportee)
  253. teleportee:set_pos(p)
  254. return true, "Teleporting <" .. rename.gpn(teleportee_name) .. "> from " .. rc.pos_to_namestr(o) .. " to <" .. rename.gpn(target_name) .. "> at " .. rc.pos_to_namestr(p) .. "."
  255. end
  256. return false, 'Invalid parameters or player not found (see /help teleport).'
  257. end