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