minetest_modding_book/_en/players/chat.md

198 lines
6.2 KiB
Markdown
Raw Normal View History

2015-09-25 02:00:15 +03:00
---
title: Chat and Commands
2015-09-25 02:00:15 +03:00
layout: default
2018-07-15 21:36:35 +03:00
root: ../..
2018-07-15 17:28:10 +03:00
idx: 4.2
description: Registering a chatcommand and handling chat messages with register_on_chat_message
2018-07-15 21:13:16 +03:00
redirect_from: /en/chapters/chat.html
2018-07-20 22:51:31 +03:00
cmd_online:
level: warning
title: Offline players can run commands
2022-06-18 23:36:02 +03:00
message: |
A player name is passed instead of a player object because mods
can run commands on behalf of offline players. For example, the IRC
bridge allows players to run commands without joining the game.
2018-07-20 22:51:31 +03:00
2022-06-18 23:36:02 +03:00
So make sure that you don't assume that the player is online.
You can check by seeing if `minetest.get_player_by_name` returns a player.
2018-07-20 22:51:31 +03:00
cb_cmdsprivs:
level: warning
title: Privileges and Chat Commands
2022-06-18 23:36:02 +03:00
message: |
The shout privilege isn't needed for a player to trigger this callback.
This is because chat commands are implemented in Lua, and are just
chat messages that begin with a /.
2018-07-20 22:51:31 +03:00
2015-09-25 02:00:15 +03:00
---
## Introduction <!-- omit in toc -->
2015-09-25 02:00:15 +03:00
Mods can interact with player chat, including
2018-10-27 05:10:37 +03:00
sending messages, intercepting messages, and registering chat commands.
2015-09-25 02:00:15 +03:00
2022-06-18 23:36:02 +03:00
- [Sending Messages](#sending-messages)
- [To All Players](#to-all-players)
- [To Specific Players](#to-specific-players)
- [Chat Commands](#chat-commands)
2022-06-18 23:36:02 +03:00
- [Accepting Multiple Arguments](#accepting-multiple-arguments)
- [Using string.split](#using-stringsplit)
- [Using Lua patterns](#using-lua-patterns)
- [Intercepting Messages](#intercepting-messages)
2015-09-25 02:00:15 +03:00
2022-06-18 23:36:02 +03:00
## Sending Messages
2015-09-25 02:00:15 +03:00
2022-06-18 23:36:02 +03:00
### To All Players
To send a message to every player in the game, call the `chat_send_all` function.
2015-09-25 02:00:15 +03:00
```lua
2015-09-25 02:00:15 +03:00
minetest.chat_send_all("This is a chat message to all players")
```
2015-09-25 02:00:15 +03:00
Here is an example of how this appears in-game:
2015-09-25 02:00:15 +03:00
<player1> Look at this entrance
This is a chat message to all players
<player2> What about it?
2015-09-25 02:00:15 +03:00
The message appears on a separate line to distinguish it from in-game player chat.
2015-09-25 02:00:15 +03:00
2022-06-18 23:36:02 +03:00
### To Specific Players
2022-06-18 23:36:02 +03:00
To send a message to a specific player, call the `chat_send_player` function:
2015-09-25 02:00:15 +03:00
```lua
2015-09-25 02:00:15 +03:00
minetest.chat_send_player("player1", "This is a chat message for player1")
```
2015-09-25 02:00:15 +03:00
This message displays in the same manner as messages to all players, but is
only visible to the named player, in this case, player1.
2015-09-25 02:00:15 +03:00
2017-10-16 18:56:31 +03:00
## Chat Commands
2015-09-25 02:00:15 +03:00
2018-10-27 05:10:37 +03:00
To register a chat command, for example `/foo`, use `register_chatcommand`:
2015-09-25 02:00:15 +03:00
```lua
2015-09-25 02:00:15 +03:00
minetest.register_chatcommand("foo", {
privs = {
2018-10-27 05:10:37 +03:00
interact = true,
},
func = function(name, param)
return true, "You said " .. param .. "!"
2018-10-27 05:10:37 +03:00
end,
2015-09-25 02:00:15 +03:00
})
```
2015-09-25 02:00:15 +03:00
2018-10-27 05:10:37 +03:00
In the above snippet, `interact` is listed as a required
[privilege](privileges.html) meaning that only players with the `interact` privilege can run the command.
2015-09-25 02:00:15 +03:00
2022-06-18 23:36:02 +03:00
`param` is a string containing everything a player writes after the chatcommand
name. For example, if a user types `/grantme one,two,three` then `param` will be
`one,two,three`.
2018-10-27 05:10:37 +03:00
Chat commands can return up to two values,
the first being a Boolean indicating success, and the second being a
message to send to the user.
2018-07-20 22:51:31 +03:00
{% include notice.html notice=page.cmd_online %}
2016-01-08 17:01:10 +03:00
2022-06-18 23:36:02 +03:00
### Accepting Multiple Arguments
2016-06-17 03:08:44 +03:00
2022-06-18 23:36:02 +03:00
<a name="complex-subcommands"></a>
2016-06-17 03:08:44 +03:00
2022-06-18 23:36:02 +03:00
`param` gives you all the arguments to a chat command in a single string. It's
common for chat commands to need to extract multiple arguments. There are two
ways of doing this, either using Minetest's string split or Lua patterns.
2022-06-18 23:36:02 +03:00
#### Using string.split
2022-06-18 23:20:15 +03:00
A string can be split up into words using `string.split(" ")`:
```lua
2022-06-18 23:20:15 +03:00
local parts = param:split(" ")
local cmd = parts[1]
if cmd == "join" then
local team_name = parts[2]
team.join(name, team_name)
return true, "Joined team!"
elseif cmd == "max_users" then
local team_name = parts[2]
local max_users = tonumber(parts[3])
if team_name and max_users then
return true, "Set max users of team " .. team_name .. " to " .. max_users
else
2022-06-18 23:23:35 +03:00
return false, "Usage: /team max_users <team_name> <number>"
2022-06-18 23:20:15 +03:00
end
else
return false, "Command needed"
end
```
2022-06-18 23:36:02 +03:00
#### Using Lua patterns
2022-06-18 23:20:15 +03:00
[Lua patterns](https://www.lua.org/pil/20.2.html) are a way of extracting stuff
from text using rules. They're best suited for when there are arguments that can
contain spaces or more control is needed on how parameters are captured.
```lua
2024-01-04 03:22:21 +03:00
local to, msg = param:match("^([%a%d_-]+) (.+)$")
```
2018-10-27 05:10:37 +03:00
The above code implements `/msg <to> <message>`. Let's go through left to right:
* `^` means match the start of the string.
* `()` is a matching group - anything that matches stuff in here will be
returned from string.match.
* `[]` means accept characters in this list.
2018-10-27 05:10:37 +03:00
* `%a` means accept any letter and `%d` means accept any digit.
2020-10-14 21:18:55 +03:00
* `[%a%d_-]` means accept any letter or digit or `_` or `-`.
2018-10-27 05:10:37 +03:00
* `+` means match the thing before one or more times.
2024-01-04 03:22:21 +03:00
* `.` means match any character in this context.
* `$` means match the end of the string.
2018-10-27 05:10:37 +03:00
Put simply, the pattern matches the name (a word with only letters/numbers/-/_),
then a space, then the message (one or more of any character). The name and
message are returned, because they're surrounded by parentheses.
That's how most mods implement complex chat commands. A better guide to Lua
Patterns would probably be the
[lua-users.org tutorial](http://lua-users.org/wiki/PatternsTutorial)
or the [PIL documentation](https://www.lua.org/pil/20.2.html).
2017-10-16 18:56:31 +03:00
## Intercepting Messages
2015-09-25 02:00:15 +03:00
To intercept a message, use register_on_chat_message:
2015-09-25 02:00:15 +03:00
```lua
2015-09-25 02:00:15 +03:00
minetest.register_on_chat_message(function(name, message)
print(name .. " said " .. message)
return false
2015-09-25 02:00:15 +03:00
end)
```
2015-09-25 02:00:15 +03:00
By returning false, you allow the chat message to be sent by the default
2018-10-27 05:10:37 +03:00
handler. You can actually remove the line `return false` and it would still
work the same, because `nil` is returned implicitly and is treated like false.
2015-09-25 02:00:15 +03:00
2018-07-20 22:51:31 +03:00
{% include notice.html notice=page.cb_cmdsprivs %}
You should make sure you take into account that it may be a chat command,
or the user may not have `shout`.
2015-09-25 02:00:15 +03:00
```lua
2015-09-25 02:00:15 +03:00
minetest.register_on_chat_message(function(name, message)
if message:sub(1, 1) == "/" then
print(name .. " ran chat command")
2018-07-20 22:51:31 +03:00
elseif minetest.check_player_privs(name, { shout = true }) then
print(name .. " said " .. message)
else
2018-09-24 19:16:00 +03:00
print(name .. " tried to say " .. message ..
" but doesn't have shout")
end
2015-09-25 02:00:15 +03:00
return false
2015-09-25 02:00:15 +03:00
end)
```