recall.lua 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. function serveressentials.emergency_recall(pname, param)
  2. local pref = minetest.get_player_by_name(pname)
  3. if not pref or not pref:is_player() then
  4. return
  5. end
  6. if param == "confirm" then
  7. local meta = pref:get_meta()
  8. local last_recall = meta:get_int("time_of_last_emergency_recall")
  9. local death_time = os.time()
  10. local cooldown = 60*60*24*3
  11. local death_pos = vector.round(pref:get_pos())
  12. if (last_recall + cooldown) >= death_time then
  13. local hours = (last_recall + cooldown) - death_time
  14. hours = math.ceil(hours / (60*60))
  15. local hstr = "hours"
  16. if hours == 1 then
  17. hstr = "hour"
  18. end
  19. minetest.log("action", "Emergency recall request from " .. pname .. " denied: cooldown")
  20. minetest.chat_send_player(pname, "# Server: Cooldown in progress. Cannot execute emergency recall at this time.")
  21. minetest.chat_send_player(pname, "# Server: Command will be available in " .. hours .. " " .. hstr .. ".")
  22. return
  23. end
  24. -- Check for nearby players. This is to ensure this command is not abused to
  25. -- escape PvP. But ignore cloaked, to prevent it from be used to scan for cloaked players.
  26. -- The very high cost should protect against casual usage in any situation.
  27. local players = minetest.get_connected_players()
  28. for k, v in ipairs(players) do
  29. local vname = v:get_player_name()
  30. -- Ignore self.
  31. if vname ~= pname then
  32. -- Ignore admin or admin-invisible.
  33. if not (gdac.player_is_admin(vname) or gdac_invis.is_invisible(vname)) then
  34. -- Ignore cloaked.
  35. if not cloaking.is_cloaked(vname) then
  36. local p2 = v:get_pos()
  37. if vector.distance(death_pos, p2) < 100 then
  38. minetest.log("action", "Emergency recall request from " .. pname .. " denied: nearby players")
  39. minetest.chat_send_player(pname, "# Server: Invalid usage. There are others nearby.")
  40. return
  41. end
  42. end
  43. end
  44. end
  45. end
  46. if meta:get_int("should_be_in_jail") ~= 0 then
  47. minetest.log("action", "Emergency recall request from " .. pname .. " denied: in jail")
  48. minetest.chat_send_player(pname, "# Server: You are in jail, you crook. Use /suicide if you are otherwise unable to commit seppuku and regain your honor.")
  49. return
  50. end
  51. if not beds.has_respawn_bed(pname) then
  52. minetest.log("action", "Emergency recall request from " .. pname .. " denied: no bed")
  53. minetest.chat_send_player(pname, "# Server: Invalid usage. You have no bed to return to.")
  54. return
  55. end
  56. minetest.log("action", pname .. " executes emergency recall from " .. minetest.pos_to_string(death_pos))
  57. -- Do it by simulating a fake death.
  58. if rc.current_realm_at_pos(death_pos) == "midfeld" then
  59. meta:set_int("abyss_return_midfeld", 1)
  60. end
  61. meta:set_string("last_death_pos", minetest.pos_to_string(death_pos))
  62. meta:set_string("last_death_time", tostring(death_time))
  63. meta:set_int("time_of_last_emergency_recall", death_time)
  64. local xp_amount = xp.get_xp(pname, "digxp")
  65. local percent_xp = xp_amount / 4
  66. if percent_xp > 10000 then percent_xp = 10000 end
  67. xp_amount = xp_amount - percent_xp
  68. if xp_amount < 0 then xp_amount = 0 end
  69. xp.set_xp(pname, "digxp", xp_amount)
  70. hud_clock.update_xp(pname)
  71. -- Exactly as if player pressed "repawn" button on respawn formspec.
  72. -- This will send player back to their bed (which they should have). It also
  73. -- handles the Midfeld spaghetti logic.
  74. beds.on_respawnplayer(pref)
  75. return
  76. end
  77. minetest.chat_send_player(pname, "# Server: type \"/emergency_recall confirm\" to run this command.")
  78. minetest.chat_send_player(pname, "# Server: You will lose 25% or 10K of your current XP as payment, whichever is less.")
  79. minetest.chat_send_player(pname, "# Server: The command cannot be used again for three realtime days.")
  80. minetest.chat_send_player(pname, "# Server: If confirmed, you will be respawned as if you had died.")
  81. minetest.chat_send_player(pname, "# Server: FOR EMERGENCY USE ONLY. Requires a bed.")
  82. end
  83. if not serveressentials.emergency_recall_registered then
  84. serveressentials.emergency_recall_registered = true
  85. minetest.register_chatcommand("emergency_recall", {
  86. params = "[confirm]",
  87. description = "Get yourself unstuck from an impossible situation. Costs XP, and has a cooldown.",
  88. privs = {interact=true},
  89. func = function(...)
  90. return serveressentials.emergency_recall(...)
  91. end
  92. })
  93. end