docs(chat-filter): block list file, portable format, phrases

How to build blocklist.dcf from blocklist.txt and where it goes, the
version 3 layout and hash, what happens to old files, and blocked
phrases; README "This branch" line. issue 215

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-30 08:05:26 -05:00
parent cef170ae47
commit 9658014b4f
3 changed files with 36 additions and 7 deletions

View File

@@ -137,6 +137,10 @@ locally. See [docs/UgcServer.md](docs/UgcServer.md).
* **World hot reload:** worlds report the zone files they loaded (`.luz`, `.lvl`, triggers, terrain, navmesh); when one
changes on disk, or on `/reloadworld` or the dashboard's Reload, master replaces those instances with new ones and
moves their players over; properties are kept until empty instead ([docs/WorldHotReload.md](docs/WorldHotReload.md)).
* **Chat filter:** the block list and the allowed words cache (`.dcf`) are hashed with 64-bit FNV-1a, so a list works
on every platform (before, `std::hash` values made on one system never matched on another); old files are refused
with a log line. Servers build `blocklist.dcf` from a plain `blocklist.txt` next to them, and blocked entries can be
phrases. See "Block list file" in [docs/Dashboard.md](docs/Dashboard.md).
* The chat server's old web API is removed; the dashboard's API covers online players, teams and announcements.
## License
@@ -375,7 +379,7 @@ All listed files are required for a server to start.
* masterconfig.ini
* WorldServer(.exe)
* worldconfig.ini
* blocklist.dcf
* blocklist.dcf (or blocklist.txt, one blocked word or phrase per line, which the servers build it from)
* migrations
* vanity
* navmeshes

View File

@@ -1213,18 +1213,42 @@ character's owner sees only what is still in their mailbox. Deleting a character
The **Chat Filter** page (GM 5+, `chat_filter_manage`, under Moderation) decides which words players below GM 2 may use
in chat. The filter's files: `chatplus_en_us.txt` (client `res` folder) lists the words normal chat may use,
`blocklist.dcf` (next to the servers, hashes only) the words best friends' free chat may not. Approved character names
also count as allowed. Words are compared lower case, without `! ? ; . ,`. Changes apply at once in running worlds and in
the chat server's web chat; servers that start later read them. Changes are audited and go to the `moderation` webhook
event.
`blocklist.dcf` (next to the servers, hashes only) the words and phrases best friends' free chat may not. Approved
character names also count as allowed. Words are compared lower case, without `! ? ; . ,`. Changes apply at once in
running worlds and in the chat server's web chat; servers that start later read them. Changes are audited and go to the
`moderation` webhook event.
Blocked entries can be phrases: a phrase is stopped when its words come in a row in a message, whatever the spaces and
punctuation between them, and the whole phrase is marked. Allowed entries are single words only, because normal
(whitelist) chat checks each word on its own, as the client does.
#### Block list file
`blocklist.dcf` is DLU's own file (the client reads no `.dcf` and doesn't hash chat words). To make or change it, put the
blocked words in `blocklist.txt` next to the servers (the build folder, beside `blocklist.dcf`): one word or phrase per
line, any case, punctuation `! ? ; . ,` ignored, blank lines skipped. The world and chat servers rebuild `blocklist.dcf`
from it when they start and it is newer than the `.dcf` (or the `.dcf` is missing or unreadable), then log how many
entries it has. With `dont_generate_dcf=1` they read `blocklist.txt` directly and write no file. `blocklist.txt` can be
removed afterwards; only the `.dcf` is needed.
Format (little-endian): `uint32` magic `DCFB`, `uint32` version `3`, `uint32` most words in one entry, `uint64` count,
then that many `uint64` hashes, sorted. Each hash is 64-bit FNV-1a (offset basis `0xcbf29ce484222325`, prime
`0x100000001b3`) over the entry's bytes: the words lower case (ASCII), without `! ? ; . ,`, joined by one space. The
same words give the same file on every platform. The allowed words cache, `chatplus_en_us.dcf` in the client's `res`
folder, uses the same format and is built from `chatplus_en_us.txt`.
Version 2 files (older DLU) stored `std::hash` values, which differ between compilers and platforms, so a list made on
one system never matched on another (issue 215). Servers refuse them: an old `chatplus_en_us.dcf` is rebuilt from
the `.txt`, and an old `blocklist.dcf` is logged as unreadable (free chat then stops every message) until it is rebuilt
from `blocklist.txt`. The **Word files** section shows which it is.
The page has three sections:
- **Test a message**: type a message, pick normal or best friends' free chat, and see whether it would be sent and why,
word by word (in the file, allowed or blocked here, a character name, not allowed, in the blocked words file). Each
word has a Block, Allow or Remove button.
- **Staff lists**: **Blocked** words are stopped in all chat, even where a file allows them; **Allowed** words are usable
in normal chat. Search, filter by list, 50 per page. Block, Allow (or move to the other list) and Remove each open a
- **Staff lists**: **Blocked** words and phrases are stopped in all chat, even where a file allows them (phrases are
marked **Phrase**); **Allowed** words are usable in normal chat. Search, filter by list, 50 per page. Block, Allow (or move to the other list) and Remove each open a
confirmation that shows where the word stands now and, for Block and Allow, the recent chat it changes (players' chat
containing it that would have been stopped, or stopped messages containing it; the newest 1000 messages with the
text; needs `chat_view`).

View File

@@ -10,6 +10,7 @@ State: **done** = fixed on this branch, needs an in-game check; **partial** = pa
|---|---|---|---|
| 159 | BUG: Brick-by-brick models are deleted instead of put away | done | `6ce261c5` fix: brick by brick and model placement work the way the client expects |
| 185 | BUG: Assembly Engineer Fortress Knockback | partial | `2d76c81b` feat: server side knockback for AI moved objects |
| 215 | ENH: Bring chat filter closer to Live | partial | `c1bcda8d` fix(chat-filter): portable .dcf hashing, block list phrases; `b279d187` shipped blocklist.dcf in the portable format; `cef170ae` dashboard phrases. The block list works on every platform and takes phrases; the rest of the issue is open |
| 225 | ENH: "bind_ip" config option | done | `e36f894f` feat: bind_ip setting for the server sockets |
| 257 | EH: Crux Prime shields stun instead of knockback | done | `2d76c81b` feat: server side knockback for AI moved objects |
| 307 | Spider Queen scream on spiderling death | done | `4900f11c` fix(scripts): the Spider Queen screams from the mountain when a spiderling dies (issue 307) |