mute_token.lua 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. if not minetest.global_exists("command_tokens") then command_tokens = {} end
  2. command_tokens.mute = command_tokens.mute or {}
  3. command_tokens.mute.players = command_tokens.mute.players or {}
  4. local mute_duration = 60*10 -- Time in seconds.
  5. -- Localize for performance.
  6. local math_random = math.random
  7. local formspec = "size[4.1,2.0]" ..
  8. default.gui_bg ..
  9. default.gui_bg_img ..
  10. default.gui_slots ..
  11. "label[0,0;Need name to mute for " .. mute_duration/60 .. " minutes:]" ..
  12. "field[0.30,0.75;4,1;PLAYERNAME;;]" ..
  13. "button_exit[0,1.30;2,1;OK;Confirm]" ..
  14. "button_exit[2,1.30;2,1;CANCEL;Cancel]" ..
  15. "field_close_on_enter[PLAYERNAME;true]"
  16. command_tokens.mute.player_muted = function(player)
  17. if command_tokens.mute.players[player] then
  18. return true
  19. else
  20. return false
  21. end
  22. end
  23. -- Called when the player uses a marker token.
  24. command_tokens.mute.mute_player = function(itemstack, user, pointed)
  25. if user and user:is_player() then
  26. local pname = user:get_player_name()
  27. if pointed.type == "object" then
  28. local object = pointed.ref
  29. if object and object:is_player() then
  30. local success = command_tokens.mute.execute(
  31. pname, object:get_player_name())
  32. if success then
  33. itemstack:take_item()
  34. return itemstack
  35. end
  36. else
  37. minetest.chat_send_player(pname, "# Server: Target is not a player!")
  38. end
  39. else
  40. minetest.show_formspec(pname, "command_tokens:mute", formspec)
  41. end
  42. end
  43. end
  44. local function unmute_on_timeout(target, rng)
  45. if command_tokens.mute.players[target] then
  46. -- This delayed callback only works if rng number matches.
  47. if command_tokens.mute.players[target] == rng then
  48. if minetest.get_player_by_name(target) then
  49. -- Player online.
  50. local dname = rename.gpn(target)
  51. minetest.chat_send_all("# Server: Player <" .. dname .. ">'s chat has been restored.")
  52. command_tokens.mute.players[target] = nil
  53. else
  54. -- Player offline.
  55. if command_tokens.mute.players[target] ~= 0 then
  56. local dname = rename.gpn(target)
  57. local str = skins.get_gender_strings(target)
  58. minetest.chat_send_all("# Server: Cannot remove ducktape from <" .. dname ..
  59. "> because " .. str.he .. "'s offline.")
  60. end
  61. command_tokens.mute.players[target] = 0
  62. minetest.after(mute_duration, unmute_on_timeout, target, 0)
  63. end
  64. end
  65. end
  66. end
  67. local function is_valid_target(target)
  68. if minetest.get_player_by_name(target) then
  69. if not minetest.check_player_privs(target, {server=true}) and
  70. not minetest.check_player_privs(target, {nomute=true}) then
  71. return true
  72. end
  73. end
  74. end
  75. command_tokens.mute.execute = function(player, target)
  76. player = rename.grn(player)
  77. target = rename.grn(target)
  78. local dname = rename.gpn(target)
  79. if is_valid_target(target) then
  80. -- Ensure player has a mute token in their inventory.
  81. local pref = minetest.get_player_by_name(player)
  82. local pinv = pref:get_inventory()
  83. local stack = ItemStack("command_tokens:mute_player")
  84. if pinv:contains_item("main", stack) then
  85. -- Mute player if they wern't muted, unmute them if they were.
  86. if not command_tokens.mute.players[target] then
  87. -- Mark this occurance with an ID that isn't likely to be already in use.
  88. -- Note: 0 has special meaning, must not be used as a random ID!
  89. local rng = math_random(1, 65000)
  90. command_tokens.mute.players[target] = rng
  91. minetest.after(mute_duration, unmute_on_timeout, target, rng)
  92. minetest.chat_send_all("# Server: Player <" .. dname .. ">'s chat has been duct-taped!")
  93. minetest.log("action", player .. " applies ducktape to " .. target)
  94. else
  95. command_tokens.mute.players[target] = nil
  96. minetest.chat_send_all("# Server: Player <" .. dname .. "> was unmuted.")
  97. minetest.log("action", player .. " unmutes " .. target)
  98. end
  99. -- Caller must consume token.
  100. return true
  101. else
  102. minetest.chat_send_player(player, "# Server: Error. Invalid usage.")
  103. end
  104. else
  105. -- Target not found.
  106. minetest.chat_send_player(player, "# Server: Player <" .. dname .. "> cannot be silenced.")
  107. end
  108. end
  109. command_tokens.mute_on_receive_fields = function(player, formname, fields)
  110. if formname == "command_tokens:mute" then
  111. if fields.key_enter_field == "PLAYERNAME" or fields.OK then
  112. local pname = player:get_player_name()
  113. local success = command_tokens.mute.execute(
  114. pname, fields.PLAYERNAME or "")
  115. if success then
  116. local inv = player:get_inventory()
  117. if inv then
  118. inv:remove_item("main", "command_tokens:mute_player")
  119. end
  120. end
  121. end
  122. end
  123. end
  124. -- Register once only.
  125. if not command_tokens.mute.registered then
  126. minetest.register_on_player_receive_fields(function(...)
  127. return command_tokens.mute_on_receive_fields(...)
  128. end)
  129. minetest.register_privilege("nomute", {
  130. description = "Player is immune to being muted.",
  131. give_to_singleplayer = false,
  132. })
  133. command_tokens.mute.registered = true
  134. end