OnPlayerText
A plain chat line - return false and nobody sees it.
Never a / command (those are OnPlayerCommandText). Anything but false lets the line through to everyone
connected, in the player’s own color. Filters, team channels, a muted player, a whisper: return false and send the line
on yourself with SendClientMessage.
The server cleans the line first: control characters and the invisible ones (zero-width spaces, the marks that flip the direction of the text, tag characters) are dropped, every kind of space becomes one plain space and a run of them one, more than three accents or other combining marks stacked on a letter are cut, the ends are trimmed and a line over 256 characters is cut. Emoji built with joiners, like a family or a heart, stay whole. A line that is empty after the cleaning never reaches the mode.
It also rations plain lines per player before the mode is asked: a burst of five, then two lines a second, and the
same line again within five seconds is dropped. The player is told “You are typing too fast.” or “You just said that.”,
at most once every three seconds, and a dropped line never reaches OnPlayerText - a mode’s database work or
filter runs on the lines that count. / commands are not rationed.
A line typed on a chat channel (RegisterChatChannel) arrives with the channel’s name as channel; a line in the
default channel has "". The server has already checked that the channel exists and that the player sees it and may
write into it - a line that fails that is refused with a notice and never gets here - and the callback runs after the
rationing above, so channel is a name the mode itself registered.
What the callback returns says what becomes of the line:
false- nobody sees it;- a text - the line goes out with those words instead;
- a table - the line goes out as that message: the shape
SendChatMessagetakes,textorspans,channel,color,templateandparams; a table that names no channel keeps the one the player typed in, and one that names another sends the line there; trueor nothing - the line goes out as typed.
A rewritten line is still the player’s: it goes out under their name, in their colour (or the channel’s, or the table’s
color), to the players the channel reaches. It is held to the limits of SendChatMessage - 16 spans, 512
characters - and a rewrite over them, an empty one, or one on a channel that does not exist is dropped and the server
log says so. A table that is not a message at all (a span that is a number, a colour that is a text) is a script error:
it is logged and counted, and the line goes out as typed - a filter that could not read its own answer does not
swallow a player’s words.
Syntax
Section titled “Syntax”function OnPlayerText(pid, text, channel) -- ...end| Parameter | Type | |
|---|---|---|
pid |
number | who typed it |
text |
string | the line, cleaned as above |
channel |
string | the channel the line was typed in - "" for the default one |
Returns
Section titled “Returns”false suppresses the line; a text replaces its words and a table replaces the whole message; anything else (or nothing) lets it through
Example
Section titled “Example”-- team chat: a line starting with "!" goes to the team alonefunction OnPlayerText(pid, text, channel) local team = GetPlayerTeam(pid) if text:sub(1, 1) == "!" and team ~= NO_TEAM then for _, other in ipairs(GetPlayers()) do if GetPlayerTeam(other) == team then SendClientMessage(other, GetPlayerColor(pid), "[team] " .. GetPlayerName(pid) .. ": " .. text:sub(2)) end end return false end
-- the trade channel takes only "<item> <price>" - drawn as a message of two pieces if channel == "trade" then local item, price = text:match("^(%a+) (%d+)$") if not item then return false end return { spans = { { text = item, bold = true }, { text = " for " .. price .. " groschen", color = COLOR_GOLD }, } } end return trueendSee also
Section titled “See also”OnPlayerCommandText · SendClientMessage · SendClientMessageToAll · the Chat and commands group of the index
