A Paper plugin: every few seconds, something chaotic happens to everyone online. Random-interval chaos loop with a MiniMessage-styled boss bar, titles, and clickable menus — start it and hang on. Five session modes.
- Platform: Paper
26.2(Bukkit API), Kotlin, JDK 25 - Package:
com.mohammadfaizan.chaos - Soft hooks: PlaceholderAPI (optional), bStats (metrics — needs an id set in
Chaos.kt) - Twitch: optional anonymous chat bridge — viewers fire effects with
!<id>, no token
Set twitch.enabled: true and twitch.channel: yourname in config.yml, then
/chaos reload. It joins your channel's chat anonymously (no OAuth) and viewers
run !<effectId> or !chaos <effectId> to fire that effect. Per-viewer and
global cooldowns are configurable; it reconnects on its own. /chaos status
shows whether the bridge is connected.
%chaos_state% · %chaos_running% · %chaos_next% (seconds) · %chaos_round% ·
%chaos_last% (last effect name) · %chaos_active% (timed effects running now) ·
%chaos_count% (loaded effects)
/chaos <sub> (alias /ch, permission chaos.admin, default op)
| Sub | Does |
|---|---|
start [mode|secs] [n] |
begin a session (see modes below); start 8 = fixed 8 s loop |
stop |
end the session, print a summary |
skip |
roll a fresh countdown without firing an effect |
force |
fire a round now, then roll a fresh countdown |
test <id> |
fire one effect immediately (ignores disabled / cooldown) — for tuning |
vote <n> |
cast a vote while one is open (or just type the number in chat) |
menu |
open the chest GUI — mode buttons, start/stop/skip, and a paginated effect on/off grid |
status |
state, mode, round, interval, and every effect id by tier — click an id to test it |
history |
list the last effects that fired |
reload |
re-read config.yml + messages.yml (applies live) |
status / history need only chaos.info (default true); everything else needs chaos.admin (op).
Modes (/chaos start <mode> [n]):
| Mode | Behaviour |
|---|---|
loop |
default — runs until stopped |
rounds <n> |
fires n effects then ends (default modes.rounds-default) |
blitz |
fast 6–10 s interval, Chaos-tier heavy, ends after modes.blitz-duration |
survival |
deaths are permanent (spectator); last player standing wins |
escalation |
interval shrinks and the Chaos tier ramps up every round |
roulette |
one effect is picked at the start and fires every round |
zen |
Easy tier only, long 45–75 s interval — ambient chaos |
Every session ends with a summary: rounds, deaths, duration, top-3 effects.
Players with chaos.exempt are never targeted (and don't count in survival).
| Key | Default | Meaning |
|---|---|---|
interval-min / interval-max |
25 / 35 |
each round waits a random seconds in this range (min 5) |
boss-bar |
true |
countdown boss bar (yellow < 10 s, red < 5 s) |
announce |
true |
chat broadcast + title + ping per effect |
preset |
normal |
safe | normal | mayhem — baseline tier weights; safe also drops griefy effects and the Chaos tier |
tier-weights.{easy,medium,chaos} |
(from preset) | commented out by default; uncomment to override the preset |
effect-weights.<id> |
10 |
per-effect weight override within its tier |
no-repeat |
2 |
don't repeat an effect until this many others have fired |
combo-chance |
0.05 |
chance a round fires 2–3 effects at once ("MEGA CHAOS") |
enabled-worlds |
[] |
restrict to these worlds (empty = all) |
resume-on-restart |
true |
resume the loop after a restart if it was running |
auto-start |
false |
start the loop on plugin load |
disabled-effects |
[] |
effect ids to exclude entirely |
vote.enabled |
false |
players vote in chat each round; most-voted effect fires (ties random) |
vote.candidates / vote.window |
3 / 12 |
how many options, and how many seconds before the effect voting opens |
modes.rounds-default / modes.blitz-duration |
20 / 120 |
defaults for rounds mode and blitz length |
Selection each round: roll a tier by weight → weighted pick within the tier
by effect-weights / the effect's own weight, skipping anything on cooldown or in
the last no-repeat fires (constraints are relaxed only if nothing else qualifies).
Targets = everyone online in Survival or Adventure, not chaos.exempt, in an
enabled world. If nobody qualifies the round is a no-op.
75 effects. /chaos status (or /chaos menu) lists them all by tier.
Each effect has a scope: ALL (default), ONE (a single random player — e.g.
spotlight, gold_rush, cursed, floor_gone, swap_with_random), or HALF
(a random half — e.g. hot_potato).
Timed effects (no_*, silence, double_damage, no_fall, floor_is_lava,
mob_magnet) impose a rule for a set number of seconds and revert themselves —
see TimedEffects + RestrictionListener. They're force-reverted when chaos
stops or the plugin disables. /chaos status lists which are active right now.
In src/main/kotlin/com/mohammadfaizan/chaos/effect/BuiltinEffects.kt: add an
object implementing ChaosEffect (id, displayName, tier, and optionally
weight / cooldownRounds, plus run(ctx)), then add it to all.
ChaosContext hands you the plugin, the non-empty target list, and a shared
Random. An exception from an effect is caught and logged — the loop continues.
./gradlew build # -> build/libs/Chaos-<version>.jar
./gradlew runServer # test on a throwaway Paper 26.2 serverRequires JDK 25 (Paper 26.1+). The Gradle wrapper jar isn't committed yet —
open in IntelliJ IDEA (it downloads Gradle 9.7.1 from gradle-wrapper.properties)
or run gradle wrapper --gradle-version 9.7.1 once.
.github/workflows/release.yml builds on every push. Bump version in
build.gradle.kts and push to publish a GitHub Release (v<version>) with the
jar attached.
- Random interval, no-repeat, per-effect weight + cooldown, presets,
/chaos test, combo rounds, per-world scope, restart resume - Timed-revert framework + 9 timed effects (no jumping / block breaking / placing / sprinting / chat, double damage, no fall, floor-is-lava, mob magnet)
- Effect library up to 45 across tiers
- PlaceholderAPI expansion + bStats wiring +
messages.ymlfor lifecycle lines - Chat-vote mode (
vote.enabled) — candidates, chat tally, random tie-break - Developer API —
ChaosAPI.register/unregister/fire+ cancellableChaosEffectEvent - MiniMessage visual style — Adventure boss bar + titles, clickable
/chaos statusand vote - Session modes —
loop/rounds/blitz/survival/escalation+ end-of-session summary - 65 effects, per-effect
scope(ALL / ONE / HALF) -
/chaos menuchest GUI — mode buttons + paginated effect on/off toggles - Twitch bridge — anonymous chat connection,
!<id>fires effects, cooldowns, auto-reconnect - Full Adventure migration of per-effect flavour text (still legacy
§) - Twitch: channel-points / bits triggers, viewer vote integration
// build against Chaos as compileOnly; softdepend: [Chaos] in plugin.yml
ChaosAPI.register(object : ChaosEffect {
override val id = "myplugin_boom"
override val displayName = "My Boom"
override val tier = EffectTier.CHAOS
override fun run(ctx: ChaosContext) { /* ... */ }
})Listen to com.mohammadfaizan.chaos.api.ChaosEffectEvent (cancellable, carries
effect, targets, source) to observe or veto any effect.