Configuration
All files live under plugins/DaisyFilter/.
| File | Purpose |
|---|---|
filters/ | Every rule DaisyFilter matches on. Editable YAML packs, loaded at runtime (see filters.md). |
config.yml | Core toggles: server label, monitor-only mode, surfaces, command profiles, filter limits, performance. |
messages.yml | Player-facing and staff-alert messages (MiniMessage). |
categories.yml | Category severities and dispositions (see categories.md). |
actions.yml | Action/effect wiring (see actions.md). |
custom-rules.yml | Server-defined literals and RE2/J-safe regular expressions. Kept for compatibility; new rules belong in filters/90-custom.yml. |
names.yml | Scanning of usernames, nicknames, and entity name tags (see below). |
spam.yml | Sliding windows, duplicate/similarity, caps/punctuation/character limits. |
escalation.yml | Severity-point escalation and opt-in punishments (disabled by default). |
allowlist.yml | Benign words and permitted domains that suppress matches. |
discord.yml | All Discord output (off by default): the bot, which posts incidents including what the player wrote and lets staff punish from Discord, plus the metadata-only webhook used as its fallback. See discord.md. |
storage.yml | SculkData database connection. |
moderation-storage.yml | Evidence privacy, retention, and write-queue settings. |
gui.yml | GUI appearance. |
runtime-overrides.yml | Machine-managed; written by the GUI and the monitor, alerts, allow, unallow, and rule commands. Also holds integration edits made in the Integrations menu, including the webhook URL and bot token, so protect it like discord.yml. Do not hand-edit. |
exports/ | Generated export archives. |
secrets/ | Generated encryption keys. Never commit or share. |
First start
Section titled “First start”DaisyFilter writes any missing file on start and never overwrites one you already have — your
edits and your filters/90-custom.yml survive every update.
The first start also needs outbound network access: the database drivers are fetched by Paper’s library loader rather than shipped in the jar. See troubleshooting.md.
Reloading
Section titled “Reloading”Run /daisyfilter reload. DaisyFilter re-reads the configuration files and every pack in filters/,
recompiles the rules and allowlist off-thread, and swaps the live snapshot
atomically only if compilation succeeds; a failed reload keeps the previous
snapshot active.
Some settings require a restart:
- the storage backend (
storage.ymldatabase type), - spam/abuse tuning (
spam.yml) apart from thesignalsblock, - escalation structure (
escalation.yml), - the chat listener priority (
config.yml→compatibility.chat-priority).
runtime-overrides.yml is never destructively rewritten over your commented
human-authored files — it only holds machine-managed state.
Key config.yml settings
Section titled “Key config.yml settings”monitor-only: forceMONITORfor everything (logs and alerts, never blocks). Toggle at runtime with/daisyfilter monitor on|off.surfaces: enable/disable chat, commands, signs, books, anvils individually.filter.max-input-length(default1280): hard scan ceiling in code points for a single scan. Text longer than this is rejected rather than filtered, so keep it above the largest legitimate input — a book page holds ~1024 characters, and pages and sign lines are scanned individually. Treat it as an abuse guard against crafted oversized payloads, not a performance knob.filter.max-book-scan-length(default32768): total code points scanned across one book edit. Needed because a book is scanned page by page, so per-scan limits leave the edit as a whole unbounded — and unlike chat, book edits run on the main thread. A book over the budget is rejected unscanned. The default clears a full vanilla-typed book (~25k code points) and only bites on pages packed past what a client can type.- Only chat is scanned off the main thread. Commands, signs, books, and anvils are scanned inline on the server thread, which is why their input bounds matter.
commands.monitored-roots/recipient-roots: which commands are scanned and which skip a recipient argument.
Name scanning (names.yml)
Section titled “Name scanning (names.yml)”A slur in a username or a pet’s name tag is visible to every child on the server, so names are scanned by the same rules as chat.
| Setting | Default | Does |
|---|---|---|
scan-player-names | true | Scan the account username when a player joins. |
scan-nicknames | true | Scan nicknames set in-game through the commands below. |
scan-entity-names | true | Scan player-set entity names, such as name tags on pets and armour stands. |
deny-login-on-block | false | Refuse the login outright when a username is blocked. |
deny-login-message | — | MiniMessage shown on the disconnect screen when a login is refused. |
nickname-commands | nick, nickname, setnick | Command roots treated as nickname changes. No leading slash. |
deny-login-on-block is off on purpose. A false positive on a message censors one line; a false
positive on a username locks a real player out of your server with no way to appeal in game. The
default is to let them in and alert staff, who can rename, mute, or ban with a human in the loop.
Only enable it if you accept that trade — a strictly whitelisted server for young children, say.
Names carry no spaces, so they are split into tokens before scanning. That is what makes a whole-word rule catch a name with digits stuck on the end.
Spam signals (spam.yml → signals)
Section titled “Spam signals (spam.yml → signals)”Each spam signal has its own disposition and severity, rather than every signal forcing a block.
Shouting is not the same offence as flooding chat, so the flood-style signals default to CENSOR:
| Signal | Default | What CENSOR does |
|---|---|---|
rate (all surfaces), duplicate-message, similar-message, word-flood | BLOCK | — |
caps-flood | CENSOR | lowercases the message |
character-flood, punctuation-flood, repeated-punctuation | CENSOR | collapses runs to two characters |
Valid dispositions are BLOCK, CENSOR, MONITOR, and ALLOW (ALLOW records the signal but takes
no action on the message). When several signals fire at once the strongest disposition wins.
Note that CENSOR only makes sense for a signal that has a defined repair — a spam signal has no
matched span to star out, so word-flood stays on BLOCK: there is no sensible way to rewrite it, and
censoring would pass the message through unchanged.
The signals block takes effect on /daisyfilter reload. The detection thresholds above it
(windows, percentages, limits) still require a restart.
Staff alerts (config.yml → alerts)
Section titled “Staff alerts (config.yml → alerts)”Staff with daisyfilter.alerts receive in-game incident notifications. By default
alerting is aggressive so staff can intervene in real time:
alert-on-block(defaulttrue): alert on every blocked message, even if the matched rule did not explicitly request an alert.censor-alert-min-severity(default2): also alert when a message is censored at or above this severity, so censored slurs/profanity are no longer silent. Raise it (e.g.4) for a quieter channel, or set0to disable censor alerts.sound(defaulttrue): play a sound to alerted staff so incidents are not missed in busy chat.sound-keyis used normally andurgent-sound-keyfor high-severity incidents (severity ≥urgent-severity, default4— slurs, grooming, safety risks). High-severity alerts also bypass the grouping cooldown so they are never dropped.
Each staffer can mute their own alerts with /daisyfilter alerts off.
Chat-plugin compatibility (config.yml → compatibility)
Section titled “Chat-plugin compatibility (config.yml → compatibility)”DaisyFilter hooks Paper’s AsyncChatEvent and edits the message component to censor,
so renderer-based formatters (EssentialsX Chat, LuckPerms/Vault formatting, etc.) display
the censored text automatically.
chat-priority(defaultLOWEST): the event priority of the chat listener. Running early lets the filter block or censor a message before chat-formatting or channel plugins broadcast or log it. Valid values:LOWEST,LOW,NORMAL,HIGH,HIGHEST. Raise it only if another plugin must transform chat before the filter sees it. Takes effect on restart.
If a chat plugin cancels AsyncChatEvent and re-broadcasts through its own system
(some channel plugins do), make sure DaisyFilter runs before it — keep chat-priority
low. On a proxy network, run DaisyFilter on each backend server, not the proxy.
GUI theming (gui.yml)
Section titled “GUI theming (gui.yml)”Menu layout is fixed (consistent, hand-tuned), but appearance is themable:
theme.pink/blue/lilac/mint: brand colours (hex) used for headings, accents, and the pink-to-blue gradient.theme.border-material/filler-material: the pane materials framing menus. Unknown material names fall back to the defaults with a console warning.theme.use-player-heads: show real player-face skulls on player menus (built from the stored UUID — no main-thread lookup). Disable for plain heads.theme.glow-primary-actions: add a glow to primary buttons (Punish, Confirm).titles.*: optional per-menu title overrides (dashboard,violations,incident,profile,history,audit,mutes,punish). Blank uses the built-in title; MiniMessage is supported. Re-apply with/daisyfilter reload.