initial commit

master
Juraj Vajda 2018-01-12 19:08:51 -05:00
commit 420b618652
12 changed files with 830 additions and 0 deletions

BIN
.gh-screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 KiB

132
API.md Normal file
View File

@ -0,0 +1,132 @@
Chat3 API
=========
Main API
--------
`chat3.colorize(name, color, msg)`
* Checks protocol of `name` and if recent enough returns the colourized `msg`
* This does not send the message to the player, but just returns the message.
* `name`: Name of player to whom the colorized message is to be sent
* `color`: Hex-code or color name (string)
* `msg`: Message to colorize
`chat3.send(name, msg, prefix, source)`
* Simulate a message being sent to all players
* `name`: Sender player name
* `msg`: Message to send
* `prefix`: An optional string to prefix the colourized message and username
* `source`: Used by ranks to allow compatibility between ranks and chat3
Ignore API
----------
`chat3.ignore.get(name)`
* Returns table of ignored players (e.g.
* `{ignoring = {name1 = true, ...}, ignored_by = {name2 = true, ...}}`)
* `name`: Player username
`chat3.ignore.set(name, list)`
* Set a player's ignore list
* `name`: Player username
* `list`: Table of names (e.g. (e.g.
* `{ignoring = {name1 = true, ...}, ignored_by = {name2 = true, ...}}`)
`chat3.ignore.add_name(name, ignore)`
* Returns `success` if `ignore` was added to `name`'s `ignoring` list and `name`
* to `ignore`'s `ignored_by` list
* `name`: Name of player to whose ignore list `ignore` should be added
* `ignore`: Player username to ignore
`chat3.ignore.remove_name(name, unignore)`
* Returns `success` if `ignore` was removed from `name`'s `ignoring` list and
* `name` from `ignore`'s `ignored_by` list
`chat3.ignore.clear(name)`
* Returns `success` if `name`'s ignore list was cleared
* This should be used over `chat3.ignore.set(name, nil)` as it also clears
* `ignored_by` lists and notifies no longer ignored players.
`name`: Name of player whose ignore list should be cleared
`chat3.ignore.can(name, check)`
* Returns `true` if the player can be ignored
* If the player cannot be ignored they will be removed from the ignore list of
* the player ignoring them.
* `name`: Name of player whose ignore list is to be checked
* `check`: Player username to check if ignored
`chat3.ignore.is(name, check)`
* Returns `true` if the player is being ignored
* `name`: Name of player whose ignore list is to be checked
* `target`: Player Object of player to check the ignore list of
`chat3.ignore.add(name, ignore)`
* Returns `success, message` after attempting to ignore a player
* Verbose, chat-friendly version of `chat3.ignore.add_name`
* `name`: Name of player to whose ignore list `ignore` should be added
* `ignore`: Player username to attempt to ignore
`chat3.ignore.remove(name, unignore)`
* Returns `success, message` after attempting to remove a player from another's
* ignore list.
* Verbose, chat-friendly version of `chat3.ignore.remove_name`
* `name`: Name of player from whose ignore list `unignore` should be removed
* `player`: Player username to attempt to unignore
`chat3.ignore.check(name, check)`
* Returns `result, message` after attempting to find out if `check` is being
* ignored by `name`.
* `name`: Name of player whose ignore list should be checked
* `check`: Player username to check if being ignored
`chat3.ignore.list(name, subtable)`
* Returns a table containing a list of players being ignored by `name`, or `nil`
* if none, in a format suitable for use with `table.concat` (e.g. `{name1, name2, ...}`).
* `name`: Name of player whose ignore list should be listed
* `subtable`: Table to return (`ignoring` or `ignored_by`)
Alternate Username API
----------------------
`chat3.alt.get(name)`
* Returns table of alternate usernames (e.g. `{name1 = true, name2 = true, ...}`)
* `name`: Player username
`chat3.alt.set(name, list)`
* Set a player's alternate username list
* `name`: Player username
* `list`: Table of alternate usernames (e.g. `{name1 = true, name2 = true, ...}`)
`chat3.alt.add(name, alt)`
* Add an alternate username (returns `nil` if max has been reached or if the
alternate username already exists)
* `name`: Base player username
* `alt`: New alternate username
`chat3.alt.remove(name, alt)`
* Remove an alternate username (returns `nil` if the username already does not
exist)
* `name`: Base player username
* `alt`: Alternate username to remove
`chat3.alt.list(name)`
* Returns a table with a list of alternate usernames (suitable for `table.concat`)
* `name`: Player username

16
LICENSE Normal file
View File

@ -0,0 +1,16 @@
MIT License
Copyright (c) 2017 Elijah Duffy
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

40
README.md Normal file
View File

@ -0,0 +1,40 @@
![Screenshot](.gh-screenshot.png)
Enhanced Chat [chat3]
=======================
- GitHub: https://github.com/octacian/chat3
- Download: https://github.com/octacian/chat3/archive/master.zip
- Forum: https://forum.minetest.net/viewtopic.php?t=17163
**Notice:** chat3 requires that the server be running Minetest 0.4.16, as it is required for several features of chat3's core functionality. More specifically, you need a version of Minetest that includes [this commit](https://github.com/minetest/minetest/commit/43d1f375d18a2fbc547a9b4f23d1354d645856ca) (May 6th, 2017).
Yes, chat3 seems a whole lot like a spinoff of chat2, however, it (mostly) isn't. It isn't that much unlike chat3, except for one thing: rather than cluttering the screen with a second chat window, chat3 just uses the default Minetest chat. Then it's entirely up to the player to configure the chat placement, size, and anything else on their client.
Messages are highlighted in a light blue to players who are within 12 blocks of the sender (configurable with `chat3.near`, if set to `0` positional highlighting is ignored). Messages in which the receiving player's name or a previously configured alternate username is mentioned are highlighted in a light green, as are PMs. Messages in which the first character is a `!` are highlighted in red to all players (also known as a shout). Important messages (mentions or shouts) also cause a bell to be played to players if `chat3.bell` is `true` and the player hasn't disabled the chatbell using the `/chatbell` command. Everything mentioned here can also be configured, and is documented below in the Configuration section.
If the server is using Minetest 0.4.16, which has the ability to properly retreive the protocol version of the client without requiring a debug build, chat3 will automatically adjust its message handling to work with older clients as well. This means that clients before 0.4.16 will not see chat duplication on their side, and colour codes will not be sent to clients that do not support them.
Chat3 is also compatible with some of my other chat-related mods, including [ranks](https://forum.minetest.net/viewtopic.php?f=9&t=17640).
Configuration
-------------
All of the features provided by chat3 can be configured directly from the advanced settings menu in the chat3 subsection of the top-level Mods section. You can also configure chat3 directly from `minetest.conf` with the settings listed below.
| Name | Type | Default | Description |
| ------------------ | ------ | ------- | ------------------------- |
| chat3.near | float | 12 | Near highlight range |
| chat3.bell | bool | true | Enable chatbell |
| chat3.shout | bool | true | Allow shout messages |
| chat3.shout_prefix | string | ! | Shout prefix |
| chat3.ignore | bool | true | Allow ignoring players |
| chat3.alt_support | bool | true | Allow alternate usernames |
| chat3.alt_max | int | 3 | Maximum # of alts |
The chatbell can also be enabled or disabled using the `/chatbell` command per-player. The ignore feature can be further configured by adding players that cannot be ignored with `ignore_override` privilege. Furthermore, the server owner (as defined by the `name` setting) cannot be ignored no matter what.
Media License
-------------
Brandon75689 - https://opengameart.org/content/point-bell (CC-BY-SA 3.0)
chat3_bell.ogg

114
alt.lua Normal file
View File

@ -0,0 +1,114 @@
-- chat3/alt.lua
chat3.alt = {}
local storage = chat3.storage
local MAX = chat3.settings.get_int("chat3.alt_max") or 3
---
--- Functions (exposed API)
---
-- [function] Get alt list
function chat3.alt.get(name)
local list = storage:get_string("alt_list_"..name)
if list then
list = minetest.deserialize(list)
end
return list or {}
end
-- [function] Set alt list
function chat3.alt.set(name, list)
storage:set_string("alt_list_"..name, minetest.serialize(list))
end
-- [function] Add alt
function chat3.alt.add(name, alt)
local list = chat3.alt.get(name)
local count = 0
for _, i in pairs(list) do
count = count + 1
end
if count < MAX and not list[alt] then
list[alt] = true
chat3.alt.set(name, list)
else
return
end
return true
end
-- [function] Remove alt
function chat3.alt.remove(name, alt)
local list = chat3.alt.get(name)
if list[alt] then
list[alt] = nil
else
return
end
chat3.alt.set(name, list)
return true
end
-- [function] List Alt Usernames (returns a table suitable for use with table.concat)
function chat3.alt.list(name)
local list, result = chat3.alt.get(name), {}
if list then
for alt, i in pairs(list) do
table.insert(result, alt)
end
if #result > 0 then
return result
end
end
end
---
--- Registrations
---
-- [chatcommand] Alt
minetest.register_chatcommand("alt", {
description = "Manage your chat3 alternate usernames",
params = "[list | add | del | rst] [<alternate username>]",
func = function(name, params)
params = params:split(" ")
local operation, alt = params[1], params[2]
if operation == "list" then
local list = chat3.alt.list(name)
if list then
return true, "Your Alternate Usernames: "..table.concat(list, ", ")
else
return false, "You have not yet configured any alternate usernames."
end
elseif operation == "add" and alt and alt ~= "" then
if chat3.alt.add(name, alt) then
return true, "Added alternate username \""..alt.."\"."
else
return false, "You have either reached the max number ("..tostring(MAX)
..") of alternate usernames, or the alternate username already exists."
end
elseif operation == "del" and alt and alt ~= "" then
if chat3.alt.remove(name, alt) then
return true, "Removed alternate username \""..alt.."\"."
else
return false, "Alternate username already does not exist."
end
elseif operation == "rst" then
chat3.alt.set(name, {})
return true, "Reset your alternate username list."
else
return false, "Invalid parameters (see /help alt)"
end
end,
})

4
description.txt Normal file
View File

@ -0,0 +1,4 @@
chat3 is a simplistic Minetest mod that makes chat on a populated server much easier to understand and keep up with.
Forum: https://forum.minetest.net/viewtopic.php?f=9&t=17163
GitHub: https://github.com/octacian/chat3

228
ignore.lua Normal file
View File

@ -0,0 +1,228 @@
-- chat3/ignore.lua
chat3.ignore = {}
local storage = chat3.storage
---
--- Functions (API)
---
-- [function] Get ignore list
function chat3.ignore.get(name)
local list = storage:get_string("ignore_list_"..name)
if list then
list = minetest.deserialize(list)
end
if not list or not list.ignoring or not list.ignored_by then
list = {ignoring = {}, ignored_by = {}}
end
return list
end
-- [function] Set ignore list
function chat3.ignore.set(name, list)
storage:set_string("ignore_list_"..name, minetest.serialize(list))
end
-- [function] Add name to list
function chat3.ignore.add_name(name, ignore)
-- Update ignoring
local list = chat3.ignore.get(name)
list.ignoring[ignore] = true
chat3.ignore.set(name, list)
-- Update ignored_by
list = chat3.ignore.get(ignore)
list.ignored_by[name] = true
chat3.ignore.set(ignore, list)
return true
end
-- [function] Remove name from list
function chat3.ignore.remove_name(name, unignore)
-- Update ignoring
local list = chat3.ignore.get(name)
list.ignoring[unignore] = nil
chat3.ignore.set(name, list)
-- Update ignored_by
list = chat3.ignore.get(unignore)
list.ignored_by[name] = nil
chat3.ignore.set(unignore, list)
return true
end
-- [function] Clear ignore list
function chat3.ignore.clear(name)
local list = chat3.ignore.get(name)
-- Clear resulting ignored_by entries and notify
for t, i in pairs(list.ignoring) do
local tlist = chat3.ignore.get(t)
tlist.ignored_by[name] = nil
chat3.ignore.set(t, tlist)
minetest.chat_send_player(t, chat3.colorize(t, "#00ff00", name..
" is no longer ignoring you."))
list.ignoring[t] = nil
end
chat3.ignore.set(name, list)
return true
end
-- [function] Can ignore
function chat3.ignore.can(name, check)
local priv = minetest.check_player_privs(check, "ignore_override")
if not priv and minetest.settings:get("name") ~= check and name ~= check then
return true
else
chat3.ignore.remove_name(name, check)
end
end
-- [function] Is Ignoring
function chat3.ignore.is(name, check)
if name == check then
return false
else
local list = chat3.ignore.get(check).ignored_by
return list[name] and chat3.ignore.can(name, check)
end
end
-- [function] Ignore
function chat3.ignore.add(name, ignore)
if chat3.ignore.can(name, ignore) then
if chat3.ignore.get(name).ignoring[ignore] then
return false, "You are already ignoring "..ignore.."."
else
chat3.ignore.add_name(name, ignore)
-- Notify ignored player
if minetest.get_player_by_name(ignore) then
minetest.chat_send_player(ignore, chat3.colorize(ignore, "red", name..
" is now ignoring you."))
end
return true, "Added "..ignore.." to your ignore list."
end
else
return false, "You cannot ignore "..ignore.."."
end
end
-- [function] Unignore
function chat3.ignore.remove(name, unignore)
if chat3.ignore.get(name).ignoring[unignore] then
chat3.ignore.remove_name(name, unignore)
-- Notify unignored player
if minetest.get_player_by_name(unignore) then
minetest.chat_send_player(unignore, chat3.colorize(unignore, "#00ff00",
name.." is no longer ignoring you."))
end
return true, "Removed "..unignore.." from your ignore list."
else
return false, unignore.." is already not on your ignore list."
end
end
-- [function] Check Ignore (verbose [chat] version if Is Ignoring)
function chat3.ignore.check(name, check)
minetest.log("chat3.ignore.check: "..name..", "..check)
if chat3.ignore.is(name, check) then
return true, "You are being ignored by "..name.."."
else
return false, name.." is not ignoring you."
end
end
-- [function] List Ignored Players (returns a table suitable for use with table.concat)
function chat3.ignore.list(name, subtable)
local list, result = chat3.ignore.get(name)[subtable], {}
if list then
for ignored, i in pairs(list) do
table.insert(result, ignored)
end
if #result > 0 then
return result
end
end
end
---
--- Registrations
---
-- [event] Show list of people ignoring you on join
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
local list = chat3.ignore.list(name, "ignored_by")
if list then
local p = "players"
if #list == 1 then
p = "player"
end
minetest.chat_send_player(name, string.format(
"You are being ignored by %i %s: %s.", #list, p,
table.concat(list, ", ")))
end
end)
-- [privilege] Ignore Override
minetest.register_privilege("ignore_override", {
description = "Prevent players from ignoring anyone with this privilege.",
give_to_singleplayer = false,
})
-- [chatcommand] Ignore
minetest.register_chatcommand("ignore", {
description = "Ignore players",
params = "[list | by | add | del | rst | check] [<player username>]",
func = function(name, params)
params = params:split(" ")
local operation, target = params[1], params[2]
local invalid = "Invalid parameters (see /help ignore)"
if operation and operation ~= "" then
if operation == "list" then
local list = chat3.ignore.list(name, "ignoring")
if list then
return true, "Ignored Players: "..table.concat(list, ", ").."."
else
return false, "You are not ignoring any players."
end
elseif operation == "by" then
local list = chat3.ignore.list(name, "ignored_by")
if list then
return true, "You are being ignored by: "..table.concat(list, ", ").."."
else
return false, "You are not being ignored by any players."
end
elseif operation == "add" and target and target ~= "" then
return chat3.ignore.add(name, target)
elseif operation == "del" and target and target ~= "" then
return chat3.ignore.remove(name, target)
elseif operation == "check" and target and target ~= "" then
return chat3.ignore.check(target, name)
elseif operation == "rst" then
chat3.ignore.clear(name)
return true, "Cleared your ignore list."
else
return false, invalid
end
else
return false, invalid
end
end,
})

259
init.lua Normal file
View File

@ -0,0 +1,259 @@
-- chat3/init.lua
chat3 = {}
chat3.settings = {}
chat3.storage = minetest.get_mod_storage()
local modpath = minetest.get_modpath("chat3")
local prot = {} -- Table of protocol versions - to be used later
---
--- Handle Settings
---
-- [function] Get float setting
function chat3.settings.get_int(key)
local res = minetest.settings:get(key)
if res then
return tonumber(res)
end
end
-- [function] Get boolean setting
function chat3.settings.get_bool(key, default)
local retval = minetest.settings:get_bool(key)
if default and retval == nil then
retval = default
end
return retval
end
local bell = chat3.settings.get_bool("chat3.bell")
local shout = chat3.settings.get_bool("chat3.shout")
local prefix = minetest.settings:get("chat3.shout_prefix") or "!"
local near = chat3.settings.get_int("chat3.near") or 12
local ignore = chat3.settings.get_bool("chat3.ignore", true)
local alt = chat3.settings.get_bool("chat3.alt_support", true)
if prefix:len() > 1 then
prefix = "!"
end
---
--- Load Features
---
if ignore then dofile(modpath.."/ignore.lua") end -- Load ignore
if alt then dofile(modpath.."/alt.lua") end -- Load alt
---
--- Exposed Functions (API)
---
-- [function] Colorize
function chat3.colorize(name, colour, msg)
local vers = prot[name]
if vers and vers >= 27 then
return minetest.colorize(colour, msg)
else
return msg
end
end
-- [function] Check if mentioned (should highlight or not)
function chat3.is_mentioned(name, msg)
name, msg = name:lower(), msg:lower()
-- Direct mentions
local direct_mention = msg:find(name, 1, true)
-- Alt mentions
local alt_mention
if alt then
local list = chat3.alt.get(name)
for alt, i in pairs(list) do
alt_mention = msg:find(alt, 1, true) or alt_mention
end
end
return direct_mention or alt_mention
end
-- [function] Process
function chat3.send(name, msg, prefix, source)
if minetest.get_modpath("ranks") and source ~= "ranks" then
return
end
local sender = minetest.get_player_by_name(name)
for _, player in pairs(minetest.get_connected_players()) do
local rname = player:get_player_name()
local colour = "#ffffff"
local vers = prot[rname]
if (not vers or (vers and (vers >= 29 or (vers < 29 and name ~= rname))))
and (not ignore or not chat3.ignore.is(rname, name)) then
-- Check for near
if near ~= 0 then -- and name ~= rname then
if vector.distance(sender:getpos(), player:getpos()) <= near then
colour = "#88ffff"
end
end
-- Check for mentions
if chat3.is_mentioned(rname, msg) then
colour = "#00ff00"
-- Chat bell
if bell and name ~= rname then
local pbell = player:get_attribute("chat3:bell")
if pbell ~= "false" then
minetest.sound_play("chat3_bell", {
gain = 4,
to_player = rname,
})
end
end
end
-- Check for shout
if shout and msg:sub(1, 1) == prefix then
colour = "#ff0000"
-- Chat bell
if bell and name ~= rname then
local pbell = player:get_attribute("chat3:bell")
if pbell ~= "false" then
minetest.sound_play("chat3_bell", {
gain = 4,
to_player = rname,
})
end
end
end
-- if same player, set to white
-- if name == rname then
-- colour = "#ffffff"
-- end
-- Send message
local send = chat3.colorize(rname, colour, "<"..name.."> "..msg)
-- if prefix then
-- send = prefix..send
-- end
minetest.chat_send_player(rname, send)
end
end
-- Log message
minetest.log("action", "CHAT: ".."<"..name.."> "..msg)
-- Prevent from sending normally
return true
end
---
--- Events/Definitions
---
-- [event] On join player
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
local info = minetest.get_player_information(name)
prot[name] = info.protocol_version
end)
-- [event] On chat message
minetest.register_on_chat_message(function(name, msg)
return chat3.send(name, msg, prefix)
end)
-- [redefine] /msg
if minetest.chatcommands["msg"] then
local old_command = minetest.chatcommands["msg"].func
minetest.override_chatcommand("msg", {
func = function(name, param)
local sendto, message = param:match("^(%S+)%s(.+)$")
if not sendto then
return false, "Invalid usage, see /help msg."
end
if not minetest.get_player_by_name(sendto) then
return false, "The player " .. sendto
.. " is not online."
end
if ignore and chat3.ignore.is(sendto, name) then
return false, chat3.colorize(name, "red",
"Could not send message, you are on "..sendto.."'s ignore list.")
else
minetest.log("action", "PM from " .. name .. " to " .. sendto
.. ": " .. message)
minetest.chat_send_player(sendto, chat3.colorize(sendto, '#00ff00',
"PM from " .. name .. ": ".. message))
if bell then
local player = minetest.get_player_by_name(sendto)
local pbell = player:get_attribute("chat3:bell")
if pbell ~= "false" then
minetest.sound_play("chat3_bell", {
gain = 4,
to_player = sendto,
})
end
end
if ignore and chat3.ignore.is(name, sendto) then
return true, "Message sent.\n"..chat3.colorize(name, "red",
"Warning: "..sendto.." will not be able to respond to this"
.." message unless you remove them from your ignore list.")
else
return true, "Message sent."
end
end
end,
})
end
-- [redefine] /me
if minetest.chatcommands["me"] then
local old_command = minetest.chatcommands["me"]
minetest.override_chatcommand("me", {
func = function(name, param)
for _, player in pairs(minetest.get_connected_players()) do
local rname = player:get_player_name()
if not ignore or not chat3.ignore.is(rname, name) then
minetest.chat_send_player(rname, "* "..name.." "..param)
end
end
end,
})
end
-- [chatcommand] Chatbell
if bell then
minetest.register_chatcommand("chatbell", {
description = "Enable/disable chatbell when you are mentioned in the chat",
func = function(name)
local player = minetest.get_player_by_name(name)
if player then
local bell = player:get_attribute("chat3:bell")
if not bell or bell == "" or bell == "true" then
player:set_attribute("chat3:bell", "false")
return true, "Disabled Chatbell"
else
player:set_attribute("chat3:bell", "true")
return true, "Enabled Chatbell"
end
end
end,
})
end

1
mod.conf Normal file
View File

@ -0,0 +1 @@
name = chat3

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 KiB

36
settingtypes.txt Normal file
View File

@ -0,0 +1,36 @@
# If this is enabled, players will have the option to hear a bell play
# whenever their name is mentioned in chat in addition to the message being
# highlighted in green.
chat3.bell (Chatbell) bool true
# If this is not set to 0, players within this range of each other will see
# messages highlighted in blue to indicate that they are close.
chat3.near (Near Highlight Range) float 12
# If this is true, players can cause messages to be highlighted in red for
# all players and the chatbell to be played (if enabled) by prefixing their
# message, by default, with "!" (configurable with chat3.shout_prefix).
chat3.shout (Enable Shout Messages) bool true
# The single-character prefix to cause messages to be highlighted in red for
# all players and the chatbell to be played (if enabled). This setting only
# applies if chat3.shout is set to true.
chat3.shout_prefix (Shout Prefix) string !
# When enabled, a /ignore chatcommand is added which allows players to ignore
# chat messages and PMs from players which they have added (see /help ignore).
# Non-ignorable players can be added with by granting the `ignore_override`.
# This will prevent these players from being added to ignore lists and will
# automatically remove them should they already exist. The server owner (as
# defined by the `name` setting) cannot be ignored no matter what.
chat3.ignore (Enable Ignore Feature) bool true
# When enabled, players can add a limitted number of alternate usernames
# which chat3 will check incoming messages for in order to expand
# highlighting. The max number of allowed alternate usernames can be
# configured with chat3.alt_max (defaults to 3).
chat3.alt_support (Allow players to add alts) bool true
# If chat3.alt_support is enabled, this will control the maximum number of
# alternate usernames that each player is allowed to configure.
chat3.alt_max (Configure maximum alts) int 3 1 1000

BIN
sounds/chat3_bell.ogg Normal file

Binary file not shown.