Skip to content

Repository files navigation

Chatty

Chatty (Bukkit plugin)

GitHub release (latest by date) GitHub All Releases GitHub code size in bytes JitPack Codacy Badge

Chatty v3 is a ground-up rewrite built on Kyori's Adventure library. It is approaching its first stable release (3.0.0); this branch holds its code.

  • Stable builds — the Releases page (once 3.0.0 is tagged).
  • Development builds — the latest artifact from the "Actions" tab (see the "Artifacts" section).

Chatty v2.* is deprecated and no longer maintained. Upgrading from v2? See MIGRATION.md — v3 migrates your old config automatically.

Chatty is the modern chat management system for Bukkit-compatible servers. It's based on-top of Kyori's Adventure library, that makes it so powerful and stable.

Key features:

  • Chat channels ("local" and "global" by default)
  • Private messaging
  • Moderation (CAPS, advertisements, swears)
  • Notifications (chat, action bar, title and advancement toasts)
  • "Vanilla" messages configuring (join/quit/death)
  • MiniMessage both legacy (&) styling format

Two kinds of per-player appearance

chats.yml has two features that both change how a message looks, and they answer different questions:

Chosen by Changes
styles the reader's permission chatty.style.<id> how the chat looks to that reader
sender-formats the sender's permission chatty.sender-format.<id> or chatty.chat.<chat>.sender-format.<id> how that player's messages look to everybody

So sender-formats is what gives a rank its own prefix in chat, and styles is what lets one reader see the chat in a different colour. They compose: the sender's rank is resolved first, and the reader's style is then taken from that rank's own styles.

chats:
  global:
    format: '{prefix}{player}: {message}'
    sender-formats:
      vip:
        priority: 10
        format: '&6[VIP] &r{player}&8: &f{message}'
        styles:
          red: { format: '&6[VIP] &r&c{player}&8: &c{message}' }

Highest priority wins when a sender qualifies for several. A rank that defines no styles is shown the same way to every reader.

Moderation

Caps, advertisement and swear filters, plus mute:

/mute <player> [10m|2h|3d|1w] [reason]    # no duration means permanent
/unmute <player>

Mutes are stored with the player, so they survive a restart and apply on every server sharing the database. A muted player cannot use public chats or private messages. chatty.command.mute grants the commands, chatty.bypass.mute exempts a player — operators hold both by default.

Placeholders

With PlaceholderAPI installed, Chatty exposes its own data so TAB, scoreboards, Discord bridges and anything else can read it:

Placeholder Value
%chatty_chat% id of the chat the player currently writes to
%chatty_chat_displayname% its display name
%chatty_chat_range% its range in blocks (-3 cross-server, -2 server, -1 world)
%chatty_chat_range_<id>% the range of a named chat, e.g. %chatty_chat_range_local%
%chatty_chat_displayname_<id>% the display name of a named chat
%chatty_prefix% / %chatty_suffix% the prefix and suffix Chatty resolves for the player
%chatty_spy% whether spy mode is on
%chatty_player_message% the last message the player sent through Chatty
%chatty_targetname% who that message named, or the player themselves
%rel_chatty_ignore% whether the first player ignores the second

%chatty_prefix% is empty unless Vault or LuckPerms is installed, because that is where the prefix comes from.

The last two describe the message a player just sent, so a command run afterwards can quote it — a Discord bridge, or a punishment naming what was said:

/discordsrv broadcast <channel> %chatty_targetname% » %chatty_player_message%
/cmi jail %player_name% said: %chatty_player_message% 2h

%chatty_targetname% is the first player mentioned in that message; with no mention it is the sender, so it is never empty for an online player.

Using the API

Add the API as a compileOnly dependency and declare Chatty as a plugin dependency — the classes come from the running plugin at runtime:

repositories { maven { url = 'https://jitpack.io' } }
dependencies { compileOnly 'ru.brikster:chatty-api:3.0.0' }
depend: [ Chatty ]

The published artifact carries Chatty's relocated Adventure, because the plugin bundles its own copy to keep working on servers that have none. That is why it must be compileOnly: a second copy on your own classpath would be a different class to the JVM. Sources and javadoc jars are published alongside it.

Platforms

Paper, Spigot and Purpur from 1.8.8 up to 26.x, and Folia. Folia support is verified by booting a real Folia server: the plugin schedules its own work and never touches the Bukkit scheduler, and the bundled bStats, which does, is skipped there.

Text formatting

Every spelling below is covered by ColourSpellingMatrixTest, so this table is what the code does rather than what it intends to do. All of them work in chat formats, in message-format, in lang/ files and in a prefix or suffix coming from LuckPerms or Vault.

Spelling Example Supported
Legacy colour &c yes
Legacy decoration &l &n &o &m &k &r yes
Section sign §c yes
MiniMessage colour <red> yes
MiniMessage hex <#757575> yes
Ampersand hex &#757575 yes
Spigot spread hex &x&7&5&7&5&7&5 yes
Gradient <gradient:#ff0000:#00ff00> yes
Rainbow <rainbow> yes
Bare hash #757575 no, prints as text

Writing colour codes in your own messages is a separate question — that needs chatty.decoration.*, see the permissions section of the migration guide.

Building

Chatty uses Gradle to handle dependencies & building. Building needs JDK 21; the jar it produces targets Java 11, so it runs on Java 11 and newer.

Compiling from source

git clone https://github.com/Brikster/Chatty.git
cd Chatty/
./gradlew build

Output jar will be placed into /build/libs directory.

Testing

Run the unit tests:

./gradlew test

Run the end-to-end smoke test — it boots real Minecraft servers with the built plugin and verifies that it enables cleanly on a fresh install, processes live in-game chat, correctly migrates a legacy v2 configuration, still runs on a legacy server (1.8.8), and coexists with DiscordSRV:

./gradlew build
JAVA_HOME=/path/to/jdk-21 bash scripts/smoke-test.sh

JAVA_HOME must point at a JDK the target server accepts: 21 for 1.21.x, 11 for 1.16.5, 25 for 26.x. Pick the server version with MC_VERSION, and switch off the parts a lane cannot run:

MC_VERSION=26.2 CHAT_TEST=0 JAVA_HOME=/path/to/jdk-25 bash scripts/smoke-test.sh

CHAT_TEST=0 skips the in-game bot, which cannot join a server newer than protocol 1.21.9, and LEGACY_SCENARIO=0 skips the 1.8.8 lane. The legacy scenario needs a Java 11 runtime; it is downloaded automatically, or point LEGACY_JAVA_HOME at an existing one.

Both run automatically on every push via GitHub Actions, with the smoke test as a matrix over 1.21.11, 1.16.5 and 26.2.

About

Bukkit-compatible chat management system

Topics

Resources

Stars

120 stars

Watchers

11 watching

Forks

Releases

Used by

Contributors

Languages