init.lua 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. if not minetest.global_exists("jaunt") then jaunt = {} end
  2. jaunt.modpath = minetest.get_modpath("jaunt")
  3. -- Localize for performance.
  4. local vector_distance = vector.distance
  5. local vector_round = vector.round
  6. -- private: assemble a formspec string
  7. function jaunt.get_formspec(player)
  8. local formspec = "size[4.5,5.5]" ..
  9. default.gui_bg ..
  10. default.gui_bg_img ..
  11. default.gui_slots
  12. formspec = formspec ..
  13. "item_image[0,0;1,1;passport:passport_adv]" ..
  14. "label[1,0;Key: Teleport to player beacon.]" ..
  15. "label[1,0.4;Requires teleport for anchor.]" ..
  16. "field[0.3,1.3;2.9,1;player;;]" ..
  17. "button[3.0,1.0;1.5,1;go;Jaunt]" ..
  18. "field_close_on_enter[player;true]" ..
  19. "button[1.25,2.0;2.25,1;cancel;Abort]" ..
  20. "label[0,3;Jaunt range is influenced by the status\nof the target's beacon. Marked players can\nbe found from farther.]" ..
  21. "item_image[1.25,4.5;1,1;command_tokens:mark_player]" ..
  22. "item_image[2.25,4.5;1,1;player_labels:show]"
  23. return formspec
  24. end
  25. -- api: show formspec to player
  26. function jaunt.show_formspec(player)
  27. local formspec = jaunt.get_formspec(player)
  28. minetest.show_formspec(player, "jaunt:fs", formspec)
  29. end
  30. -- Find nearby teleport, and return its range.
  31. function jaunt.valid_teleport(pos)
  32. local tar = minetest.find_node_near(pos, 2, "teleports:teleport", true)
  33. if tar then
  34. -- Range is halved because when we're jaunting, there is no teleport at the
  35. -- other end to receive us! Also, this means that when using a nyan TP, the
  36. -- range is more-or-less the same as the original, hard-coded jaunt range.
  37. local range = teleports.calculate_range(tar)
  38. return true, (range * 0.5)
  39. end
  40. end
  41. jaunt.on_receive_fields = function(player, formname, fields)
  42. if formname ~= "jaunt:fs" then return end
  43. local pname = player:get_player_name()
  44. -- security check to make sure player can use this feature
  45. if not passport.player_has_key(pname) then
  46. return true
  47. end
  48. if not survivalist.player_beat_cave_challenge(pname) then
  49. return true
  50. end
  51. -- Jaunt ability is revoked for cheaters.
  52. if sheriff.is_cheater(pname) then
  53. return true
  54. end
  55. if fields.cancel then
  56. passport.show_formspec(pname)
  57. return true
  58. end
  59. if fields.quit then
  60. return true
  61. end
  62. local uspos = vector_round(player:get_pos())
  63. if fields.key_enter_field == "player" or fields.go then
  64. local success, tp_range = jaunt.valid_teleport(uspos)
  65. if success then -- Teleport was found.
  66. local target = rename.grn((fields.player or ""):trim())
  67. if target ~= pname then
  68. local other = minetest.get_player_by_name(target)
  69. if other and other:is_player() and not cloaking.is_cloaked(target) then
  70. local marked = command_tokens.mark.player_marked(target)
  71. local beacon = player_labels.query_nametag_onoff(target)
  72. -- a player can be located if either they're marked or their beacon (nametag) is activated
  73. if marked or beacon then
  74. if passport.player_has_key(target) then
  75. -- if a player is marked, but their beacon is off, then the range at which
  76. -- they can be detected is halved
  77. local range = tp_range
  78. if not marked and not beacon then
  79. -- Not marked, nametag off.
  80. range = range * 0.25
  81. elseif marked and not beacon then
  82. -- Nametag off, but marked.
  83. range = range * 0.5
  84. elseif marked and beacon then
  85. -- Nametag on and marked.
  86. range = range * 1.5
  87. end
  88. local tarpos = other:get_pos()
  89. tarpos.y = tarpos.y + 1
  90. tarpos = vector_round(tarpos)
  91. local total_dist = vector_distance(tarpos, uspos)
  92. -- Take 1 second per 100 meters traveled.
  93. local spinup_time = math.floor(total_dist / 100)
  94. -- Randomize target position a bit.
  95. tarpos.x = tarpos.x + math.random(-1, 1)
  96. tarpos.z = tarpos.z + math.random(-1, 1)
  97. -- Make sure it's air.
  98. local finpos = minetest.find_node_near(tarpos, 2, "air", true)
  99. -- Make sure target isn't standing in/on something that disallows teleport.
  100. if true then
  101. local nodename = sky.get_last_walked_node(target)
  102. local ndef = minetest.registered_nodes[nodename]
  103. if ndef and ndef.disallow_teleport then
  104. finpos = nil
  105. end
  106. nodename = sky.get_last_walked_nodeabove(target)
  107. ndef = minetest.registered_nodes[nodename]
  108. if ndef and ndef.disallow_teleport then
  109. finpos = nil
  110. end
  111. end
  112. if finpos and rc.current_realm_at_pos(finpos) == rc.current_realm_at_pos(uspos) then
  113. if total_dist < range then
  114. -- Alert player that someone's coming to them.
  115. local RED = core.get_color_escape_sequence("#ff0000")
  116. minetest.chat_send_player(target,
  117. RED .. "# Server: Alert! Incoming jaunt from <" ..
  118. rename.gpn(pname) .. ">.")
  119. chat_core.alert_player_sound(target)
  120. -- Teleport player to chosen location.
  121. preload_tp.execute({
  122. player_name = pname,
  123. target_position = finpos,
  124. send_blocks = true,
  125. particle_effects = true,
  126. spinup_time = spinup_time,
  127. -- Pre-teleport callback.
  128. pre_teleport_callback = function()
  129. -- Abort teleport if player logged off.
  130. if not minetest.get_player_by_name(target) then
  131. minetest.chat_send_player(pname, "# Server: Lost link to target beacon.")
  132. return true -- Abort transport.
  133. end
  134. -- Abort teleport if target player cloaked themselves.
  135. if cloaking.is_cloaked(target) then
  136. minetest.chat_send_player(pname, "# Server: Lost link to target beacon.")
  137. return true -- Abort transport.
  138. end
  139. end,
  140. -- Post-teleport callback.
  141. post_teleport_callback = function()
  142. portal_sickness.on_use_portal(pname)
  143. end,
  144. })
  145. -- don't reshow the formspec
  146. minetest.close_formspec(pname, "jaunt:fs")
  147. return true
  148. else
  149. minetest.chat_send_player(pname, "# Server: Target Key's signal origin is too weak to accurately triangulate!")
  150. end
  151. else
  152. minetest.chat_send_player(pname, "# Server: Could not detect evidence of a Key's beacon signal.")
  153. end
  154. else
  155. minetest.chat_send_player(pname, "# Server: Could not detect evidence of a Key's beacon signal.")
  156. end
  157. else
  158. minetest.chat_send_player(pname, "# Server: Could not detect evidence of a Key's beacon signal.")
  159. end
  160. else
  161. minetest.chat_send_player(pname, "# Server: Could not detect evidence of a Key's beacon signal.")
  162. end
  163. else
  164. minetest.chat_send_player(pname, "# Server: Cleverly refusing to scan for your own Key's beacon signal.")
  165. end
  166. else
  167. minetest.chat_send_player(pname, "# Server: Key requires access to proximate teleport to deploy this function.")
  168. end
  169. end
  170. jaunt.show_formspec(pname)
  171. return true
  172. end
  173. if not jaunt.registered then
  174. minetest.register_on_player_receive_fields(function(...)
  175. return jaunt.on_receive_fields(...)
  176. end)
  177. local c = "jaunt:core"
  178. local f = jaunt.modpath .. "/init.lua"
  179. reload.register_file(c, f, false)
  180. jaunt.registered = true
  181. end