- Java 100%
| src/main | ||
| .gitignore | ||
| build.gradle.kts | ||
| LICENSE | ||
| README.md | ||
| settings.gradle.kts | ||
eternel-chat-plugin (EternelChat)
In-game ↔ web chat bridge for eternel.eu / minecraftanarchy.com, built as a backend Folia plugin (Luminol 26.1.2, protocol 776/26.2, Java 25) rather than a mineflayer bot or Velocity plugin — so it can leverage ChatControl for formatting + profanity filtering.
What it does
- On enable: reads
plugins/EternelChat/config.yml(relay URL + shared secret), opens an auto-reconnecting outbound WebSocket (client) to the relay containerws://chat-service:8081/ingest?key=<secret>. No inbound port on the MC server. - game → web: reads the final chat line via ChatControl's
ChannelPostChatEvent(post-filter, authoritative; ChatControl frequently cancels the BukkitAsyncChatEvent) atMONITOR. Falls back toAsyncChatEventif ChatControl is absent. Sends{type:'chat',name,text,ts}to the relay. - web → game: on
{type:'send',name,text}from the relay, posts"[web] <name>: <text>"in-game throughChatControlAPI.sendMessage(console, "standard", msg)so ChatControl's format + filter + fan-out apply. Clean Adventure broadcast fallback if ChatControl is unavailable.
Folia correctness
folia-supported: trueinplugin.yml.- Chat events are read-only on async chat threads (no world access).
- All world-touching / player delivery (web→game) runs on
GlobalRegionScheduler. - WebSocket lifecycle runs on a dedicated daemon scheduler + the Java-WebSocket reader thread — never blocks a region thread.
- Never uses
Bukkit.getScheduler().
Build
Folia API dev.folia:folia-api:1.21.11-R0.1-SNAPSHOT (compileOnly, from PaperMC repo). ChatControl 12.1.7 is a local compileOnly files("libs/ChatControl-12.1.7.jar") (not on Maven Central). Java toolchain 25, options.release = 21 → bytecode 65. org.java-websocket:Java-WebSocket + org.json are shaded and relocated under fr.ekaii.eternelchat.shaded.*.
docker run --rm -v $PWD:/work -v ~/.gradle-cache:/home/gradle/.gradle \
-w /work gradle:9.6-jdk25-noble gradle --no-daemon clean build
# -> build/libs/EternelChat-<version>.jar
libs/ChatControl-12.1.7.jaris required to build but is not committed (it is the proprietary ChatControl-Red jar). Copy it from the server'splugins/dir before building.
Architecture
The relay is a separate Coolify Docker-Compose service chat-service (Node + ws) that serves browsers at wss://your-domain/chat and accepts the plugin at /ingest (shared-secret guarded). Rate-limit + EN/FR slur filter for the public widget live in the relay; ChatControl is defence-in-depth.