chatcommands.lua 5.1 KB

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