Periodic chat games where the first correct answer wins. Trivia, unscramble, math, typing races, fully configurable.

ChatActivities runs games in chat on a timer. It posts a question, and the first player to type the correct answer wins whatever rewards you configure.
Nine game types ship with it, from hand-written trivia to generated word puzzles and arithmetic. Everything is configurable: the questions, how strictly answers are matched, how often games run, what winning gives you, and every line of text players see.


- Five generated game types plus your own hand-written questions
- Whole question banks in one entry so a large trivia pool does not swamp your other games
- Flexible answer matching with exact, contains, regex or fuzzy modes, and typo tolerance
- Progressive hints that reveal the answer gradually and never give it away completely
- Reward commands run from console or as the winner, with placeholder support
- Win statistics with a leaderboard and fastest-time tracking, stored in SQLite
- PlaceholderAPI in both directions: use
%placeholders%in rewards, and expose%chatactivities_...%to your scoreboards and holograms - Players can opt out with a single command if they would rather not see the games
- MiniMessage formatting throughout, with optional sounds, titles and action bars
- A developer API with four events so other plugins can filter, redirect or react

- Drop the jar into your
pluginsfolder - Restart the server
- Edit
plugins/ChatActivities/games.ymlandconfig.yml - Run
/ca reload
Requirements
- Paper 26.2
- Java 25 or newer
Optional
- PlaceholderAPI, if you want to use
%placeholders%in reward commands or show ChatActivities stats in other plugins
Java 25 is required. Paper 26.2 needs it too, so this plugin cannot run on anything older. Run java -version to
check before you install.
The first time the plugin starts it downloads one extra file it needs for saving statistics, around 12 MB. This is automatic and happens only once, but your server needs internet access for it. Without it the plugin will not start.

A game is either static (you write the question and its answers) or generated (a type: produces both fresh
each round).
Game type (type) |
What players see | Answer |
|---|---|---|
| none | Your question, your answers | Whatever you listed |
unscramble |
domniad |
diamond |
reversed |
regalliv |
villager |
random-string |
f6zqqh |
The string, a pure typing race |
random-trivia |
A question drawn from your pool | That entry's answers |
math |
9 + 22, √49, 20% of 150, 12² |
The result |
A static question
games:
capital-france:
question: "<gold>Quick!</gold> <white>What is the capital of France?"
answers: [ "paris" ]
notification: trivia
timeout: 30s
commands:
- "console: say {player} knew it in {time}!"
A whole trivia bank in one entry
Prefer this over one game per question. A hundred separate entries would crowd out every other game when selection is weighted.
general-trivia:
type: random-trivia
question: "<gold>Trivia:</gold> <white>{question}"
pool:
- q: "Which mob explodes when it gets close to you?"
a: [ "creeper" ]
- q: "What is the strongest vanilla armour material?"
a: netherite # a single answer needs no brackets
Arithmetic
mode picks the flavour: expression, square, root or percent. Division is always exact, so answers are never
fractions.
quick-maths:
type: math
question: "<yellow>Solve:</yellow> <white>{problem}"
mode: expression
operations: [ add, subtract, multiply, divide ]
operands: "2-25"
terms: 2

Main command is /chatactivities, with /chatact and /ca as aliases.
| Command | Permission | Default |
|---|---|---|
/ca start [game] |
chatactivities.admin |
op |
/ca stop |
chatactivities.admin |
op |
/ca reload |
chatactivities.admin |
op |
/ca list |
chatactivities.admin |
op |
/ca toggle |
chatactivities.toggle |
everyone |
/ca stats [player] |
chatactivities.stats |
everyone |
/ca top |
chatactivities.stats |
everyone |
Viewing another player's stats needs chatactivities.stats.other (op by default). Each game also registers
chatactivities.receive.<notification>, granted to everyone by default. Revoke it to hide a particular category of game
from a group.

Three files, all reloadable with /ca reload. A malformed game is reported by name in the console and skipped, so one bad entry never stops the rest from loading.
config.yml holds timing, matching, hints, rewards and storage.
timing:
interval: 300s # base delay between games
variance: 60s # actual delay is the interval plus or minus this
timeout: 45s # how long players have to answer
min-players: 2 # below this, the scheduler waits
selection:
mode: weighted # random | weighted
avoid-repeat: 3 # don't replay any of the last N games
matching:
mode: exact # exact | contains | regex | fuzzy
fuzzy-tolerance: 1 # how many typos to forgive
Matching is always case-insensitive. There is deliberately no option for it.
Hints reveal the answer a little at a time, and are capped so the final character is always hidden. Answers shorter
than min-answer-length get no hints at all, because on a two-character answer even the first hint would hand it over.
Rewards accept a console: or player: prefix and the placeholders {player}, {uuid}, {game}, {answer} and
{time}. default-commands run when a game defines none of its own; always-commands run on every win regardless.
games.yml holds the games, messages.yml every line of text, in
MiniMessage format. Any message can also carry a sound, title, subtitle, action bar or boss bar.

Using placeholders. If PlaceholderAPI is installed, %placeholders% from any expansion are resolved in reward
commands. This applies to reward commands only, not to messages.yml or to game questions.
Providing placeholders. Other plugins can read these:
| Placeholder | Value |
|---|---|
%chatactivities_wins% |
The player's total wins |
%chatactivities_fastest% |
Their best time, e.g. 1.42s |
%chatactivities_fastest_ms% |
Their best time in milliseconds |
%chatactivities_rank% |
Leaderboard position |
%chatactivities_total_wins% |
Every win on the server |
%chatactivities_total_players% |
Players who have won at least once |
%chatactivities_active% |
true while a game is running |
%chatactivities_active_game% |
The running game's name |
%chatactivities_top_name_1% |
Name at that place |
%chatactivities_top_wins_1% |
Wins at that place |
%chatactivities_top_fastest_1% |
Best time at that place |
Values come from a cache that refreshes on a configurable interval, so scoreboards asking many times a second never touch the database.

Four events, all on the main thread.
| Event | Cancellable | Fired |
|---|---|---|
ChatActivityStartEvent |
yes | Before a game is broadcast |
ChatActivityBroadcastEvent |
yes | For every message sent, with a mutable recipient set |
ChatActivityWinEvent |
yes | On a correct answer, before rewards run |
ChatActivityEndEvent |
no | When a round ends, however it ended |
ChatActivityBroadcastEvent is the integration point for chat management plugins. It carries the message, the game, its notification tag and the recipients, all of which you can change.
Writing a separate plugin against this API is explicitly permitted by the licence, and your plugin remains entirely your own.
Licence: All Rights Reserved. You may run ChatActivities on any server you operate. You may not redistribute, modify or resell it.
If you encounter any issues, message me on Discord @escyth.
Information
Pinned Versions
- R26.2
Pages
Members
1Owner