chatcommands.lua 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. -- Minetest: builtin/common/chatcommands.lua
  2. -- For server-side translations (if INIT == "game")
  3. -- Otherwise, use core.gettext
  4. local S = core.get_translator("__builtin")
  5. core.registered_chatcommands = {}
  6. -- Interpret the parameters of a command, separating options and arguments.
  7. -- Input: command, param
  8. -- command: name of command
  9. -- param: parameters of command
  10. -- Returns: opts, args
  11. -- opts is a string of option letters, or false on error
  12. -- args is an array with the non-option arguments in order, or an error message
  13. -- Example: for this command line:
  14. -- /command a b -cd e f -g
  15. -- the function would receive:
  16. -- a b -cd e f -g
  17. -- and it would return:
  18. -- "cdg", {"a", "b", "e", "f"}
  19. -- Negative numbers are taken as arguments. Long options (--option) are
  20. -- currently rejected as reserved.
  21. local function getopts(command, param)
  22. local opts = ""
  23. local args = {}
  24. for match in param:gmatch("%S+") do
  25. if match:byte(1) == 45 then -- 45 = '-'
  26. local second = match:byte(2)
  27. if second == 45 then
  28. return false, S("Invalid parameters (see /help @1).", command)
  29. elseif second and (second < 48 or second > 57) then -- 48 = '0', 57 = '9'
  30. opts = opts .. match:sub(2)
  31. else
  32. -- numeric, add it to args
  33. args[#args + 1] = match
  34. end
  35. else
  36. args[#args + 1] = match
  37. end
  38. end
  39. return opts, args
  40. end
  41. function core.register_chatcommand(cmd, def)
  42. def = def or {}
  43. def.params = def.params or ""
  44. def.description = def.description or ""
  45. def.privs = def.privs or {}
  46. def.mod_origin = core.get_current_modname() or "??"
  47. core.registered_chatcommands[cmd] = def
  48. end
  49. function core.unregister_chatcommand(name)
  50. if core.registered_chatcommands[name] then
  51. core.registered_chatcommands[name] = nil
  52. else
  53. core.log("warning", "Not unregistering chatcommand " ..name..
  54. " because it doesn't exist.")
  55. end
  56. end
  57. function core.override_chatcommand(name, redefinition)
  58. local chatcommand = core.registered_chatcommands[name]
  59. assert(chatcommand, "Attempt to override non-existent chatcommand "..name)
  60. for k, v in pairs(redefinition) do
  61. rawset(chatcommand, k, v)
  62. end
  63. core.registered_chatcommands[name] = chatcommand
  64. end
  65. local function format_help_line(cmd, def)
  66. local cmd_marker = INIT == "client" and "." or "/"
  67. local msg = core.colorize("#00ffff", cmd_marker .. cmd)
  68. if def.params and def.params ~= "" then
  69. msg = msg .. " " .. def.params
  70. end
  71. if def.description and def.description ~= "" then
  72. msg = msg .. ": " .. def.description
  73. end
  74. return msg
  75. end
  76. local function do_help_cmd(name, param)
  77. local opts, args = getopts("help", param)
  78. if not opts then
  79. return false, args
  80. end
  81. if #args > 1 then
  82. return false, S("Too many arguments, try using just /help <command>")
  83. end
  84. local use_gui = INIT == "client" or core.get_player_by_name(name)
  85. use_gui = use_gui and not opts:find("t")
  86. if #args == 0 and not use_gui then
  87. local cmds = {}
  88. for cmd, def in pairs(core.registered_chatcommands) do
  89. if INIT == "client" or core.check_player_privs(name, def.privs) then
  90. cmds[#cmds + 1] = cmd
  91. end
  92. end
  93. table.sort(cmds)
  94. local msg
  95. if INIT == "game" then
  96. msg = S("Available commands: @1",
  97. table.concat(cmds, " ")) .. "\n"
  98. .. S("Use '/help <cmd>' to get more "
  99. .. "information, or '/help all' to list "
  100. .. "everything.")
  101. else
  102. msg = core.gettext("Available commands: ")
  103. .. table.concat(cmds, " ") .. "\n"
  104. .. core.gettext("Use '.help <cmd>' to get more "
  105. .. "information, or '.help all' to list "
  106. .. "everything.")
  107. end
  108. return true, msg
  109. elseif #args == 0 or (args[1] == "all" and use_gui) then
  110. core.show_general_help_formspec(name)
  111. return true
  112. elseif args[1] == "all" then
  113. local cmds = {}
  114. for cmd, def in pairs(core.registered_chatcommands) do
  115. if INIT == "client" or core.check_player_privs(name, def.privs) then
  116. cmds[#cmds + 1] = format_help_line(cmd, def)
  117. end
  118. end
  119. table.sort(cmds)
  120. local msg
  121. if INIT == "game" then
  122. msg = S("Available commands:")
  123. else
  124. msg = core.gettext("Available commands:")
  125. end
  126. return true, msg.."\n"..table.concat(cmds, "\n")
  127. elseif INIT == "game" and args[1] == "privs" then
  128. if use_gui then
  129. core.show_privs_help_formspec(name)
  130. return true
  131. end
  132. local privs = {}
  133. for priv, def in pairs(core.registered_privileges) do
  134. privs[#privs + 1] = priv .. ": " .. def.description
  135. end
  136. table.sort(privs)
  137. return true, S("Available privileges:").."\n"..table.concat(privs, "\n")
  138. else
  139. local cmd = args[1]
  140. local def = core.registered_chatcommands[cmd]
  141. if not def then
  142. local msg
  143. if INIT == "game" then
  144. msg = S("Command not available: @1", cmd)
  145. else
  146. msg = core.gettext("Command not available: ") .. cmd
  147. end
  148. return false, msg
  149. else
  150. return true, format_help_line(cmd, def)
  151. end
  152. end
  153. end
  154. if INIT == "client" then
  155. core.register_chatcommand("help", {
  156. params = core.gettext("[all | <cmd>] [-t]"),
  157. description = core.gettext("Get help for commands (-t: output in chat)"),
  158. func = function(param)
  159. return do_help_cmd(nil, param)
  160. end,
  161. })
  162. else
  163. core.register_chatcommand("help", {
  164. params = S("[all | privs | <cmd>] [-t]"),
  165. description = S("Get help for commands or list privileges (-t: output in chat)"),
  166. func = do_help_cmd,
  167. })
  168. end