Velocity plugin that provides an API and a plugin message channel for sending messages on ChatControl channels. Requires VelocityControl to be installed.
- Programmatic API: Other Velocity plugins can send a message on any ChatControl channel.
- Plugin message channel: Backend servers (e.g. Bukkit) can send a payload on the
chatcontrolmirror:sendchannel to forward a message to a channel. - Redis: Anything that can publish to Redis can send a JSON payload to a channel. Works when the sending backend has no players online.
Obtain the API from the plugin container:
proxy.getPluginManager().getPlugin("chatcontrolmirror")
.flatMap(container -> container.getInstance())
.filter(ChatControlMirror.class::isInstance)
.map(ChatControlMirror.class::cast)
.map(ChatControlMirror::getApi)
.ifPresent(api -> api.sendChannelMessage("staff", "Hello &aworld", MessageFormat.LEGACY));- channelName: Must match a ChatControl channel (e.g.
staff). - message: The message text. Format depends on the third parameter.
- format:
MessageFormat.LEGACY(e.g.&a,§a) orMessageFormat.MINIMESSAGE(e.g.<green>text</green>).
The sender is fixed (e.g. "Server") and bypass flags are false.
Channel: chatcontrolmirror:send (Minecraft channel identifier).
Payload: A byte array of three length-prefixed UTF strings (Java DataOutputStream.writeUTF / DataInputStream.readUTF style: 2-byte unsigned length in big-endian, then UTF-8 bytes), in order:
- channel – ChatControl channel name
- type –
"LEGACY"or"MINIMESSAGE" - message – Message text (decoded according to
type)
Example (Java backend): write the three strings with DataOutputStream.writeUTF(channel); writeUTF(type); writeUTF(message); and send the resulting byte array.
A plugin message from a backend needs a connected player to travel through, so a backend with no players online can't use it. The Redis input has no such limit: the proxy subscribes to a Redis pub/sub channel and forwards each message it receives.
plugins/chatcontrolmirror/config.yml is created on first start. Redis is off by default.
| Key | Default | Description |
|---|---|---|
redis.enabled |
false |
Turn the Redis input on. |
redis.host |
localhost |
Redis host. |
redis.port |
6379 |
Redis port. |
redis.password |
"" |
Redis password. Empty means no auth. |
redis.channel |
chatcontrolmirror:send |
Pub/sub channel to subscribe to. |
The config is read at proxy startup. If Redis is unreachable the plugin logs a warning and keeps retrying in the background; the plugin message channel and /ccmsend work either way.
A JSON object published as a string:
{"channel": "global", "type": "MINIMESSAGE", "message": "<gold>[Comp]</gold> Lobby is open"}- channel (required): ChatControl channel name.
- type:
LEGACYorMINIMESSAGE. Missing or unknown values are treated asLEGACY. - message (required): Message text, decoded according to
type.
Malformed JSON or a missing field is logged as a warning and the message is dropped. With /ccmdebug on, every received message is logged.
redis-cli PUBLISH chatcontrolmirror:send '{"channel":"global","type":"MINIMESSAGE","message":"<click:run_command:''/comp''><gold>Join the comp</gold></click>"}'/ccmsend <channel> <type> <message...>– Test command to send a message on a channel.typeisLEGACYorMINIMESSAGE; everything after the second argument is the message (spaces allowed). Permission:chatcontrolmirror.send. Logs to the plugin logger./ccmdebug– Toggle debug mode (in-memory only, resets on restart). When enabled, logs received plugin messages, Redis messages and API send calls. Permission:chatcontrolmirror.debug.
Targets Java 25 and needs a JDK 25 toolchain. Built against VelocityControl 3.1.13 (vcVersion in gradle.properties). That version isn't in the Maven repo yet, so place VelocityControl-3.1.13.jar in the lib/ directory and run:
./gradlew buildThe plugin jar is build/libs/ChatControlMirror-<version>.jar. It shades and relocates the Jedis Redis client.
See repository.