How It Works
A single neutral flag spawns at the centre of an arena. Either team — RED or BLUE — can grab it and carry it back to their own base to score. First team to the arena's captures-to-win wins; if the clock runs out, the higher score wins (equal = draw).
Players fight with their own gear and ShardsSMPv2 shard abilities — CTF gives no kit and strips nothing.
The carrier wears the flag banner on their head and glows in their team colour (visible through walls).
A carrier who dies or leaves the bounds drops the flag where they fell; it returns to centre after a timer if nobody grabs it.
Match deaths never cost a real life or trigger penalties. Gear is kept, you respawn at your team spawn with brief protection.
Out of bounds? Leaving the arena or falling into the void teleports you safely back to your spawn — no damage.
Building Arenas
Do this in-game as an op. Arena geometry is captured from where you are standing, so these commands can't be run from console. Everything goes into an in-memory draft until you /ctf arena save.
- 1
/ctf arena create <name>Start a draft.
- 2
/ctf arena set spawn red · set spawn blueStand on each team's spawn point and run the command there.
- 3
/ctf arena set base red · set base blueStand on each team's base — where they carry the flag to score.
- 4
/ctf arena set flagStand at the flag centre (where the neutral flag spawns).
- 5
/ctf arena set bounds 1 · set bounds 2Stand at two opposite corners to mark the play area.
- 6
/ctf arena saveValidate and lock it in. Save refuses an incomplete draft and lists what's missing.
Save requires all six points
/ctf arena save refuses an incomplete draft and tells you what's missing. All points must be in the same world. Required:
Editing later: /ctf arena edit <name> loads an existing arena back into a draft so you can re-set points, then save again.
Commands
shardsctf.play· default: everyoneJoin / leave / view matches.
shardsctf.admin· default: OPBuild arenas & run matches.
Player Commands
| Command | Description |
|---|---|
/ctf | Show the help / command list. |
/ctf join <arena> | Join an arena's lobby — you're auto-assigned to the smaller team. |
/ctf leave | Leave your current match or lobby. |
/ctf list | List all defined arenas. |
/ctf info <arena> | Show an arena's settings and live state. |
Match Control(shardsctf.admin)
| Command | Description | Permission |
|---|---|---|
/ctf start <arena> | Force-start a waiting match (needs ≥ min-players per team). | shardsctf.admin |
/ctf stop <arena> | Abort a running match. Not recorded to stats. | shardsctf.admin |
/ctf reload | Reload config.yml, messages.yml and arenas.yml. | shardsctf.admin |
Arena Building(shardsctf.admin · in-game only)
| Command | Description | Permission |
|---|---|---|
/ctf arena create <name> | Begin a new arena draft. | shardsctf.admin |
/ctf arena edit <name> | Load an existing arena back into a draft. | shardsctf.admin |
/ctf arena delete <name> | Delete an arena (refused while a match runs in it). | shardsctf.admin |
/ctf arena save | Validate and persist the current draft to arenas.yml. | shardsctf.admin |
/ctf arena set spawn <red|blue> | Set a team's spawn to your location. | shardsctf.admin |
/ctf arena set base <red|blue> | Set a team's base (scoring point) to your location. | shardsctf.admin |
/ctf arena set flag | Set the neutral flag's centre to your location. | shardsctf.admin |
/ctf arena set bounds <1|2> | Set play-area corner 1 or 2 to your location. | shardsctf.admin |
/ctf arena set captures <n> | Captures needed to win (min 1). | shardsctf.admin |
/ctf arena set duration <seconds> | Match length (min 30). | shardsctf.admin |
/ctf arena set capture-radius <blocks> | Grab / score proximity radius (min 1.0). | shardsctf.admin |
/ctf arena set flag-return <seconds> | Dropped-flag return timer (min 1). | shardsctf.admin |
/ctf arena set min-players <n> | Min players per team to start (min 1). | shardsctf.admin |
/ctf arena set max-players <n> | Max players per team (0 = unlimited). | shardsctf.admin |
A match begins automatically when both teams reach auto-start-players-per-team, or when an op runs /ctf start <arena>.
Configuration
config.yml holds runtime behaviour and the defaults a brand-new arena is created with. Per-arena geometry lives in arenas.yml (managed by commands — don't hand-edit). Run /ctf reload after changes.
match:
| Key | Default | Meaning |
|---|---|---|
countdown-seconds | 5 | Pre-match "5…4…3…2…1…GO" countdown. |
spawn-protection-seconds | 3 | Damage immunity on (re)spawn (0 = off). |
out-of-bounds-check-interval-ticks | 10 | Bounds / flag-proximity scan rate (20 = 1s). |
hud-refresh-ticks | 20 | Sidebar scoreboard + timer refresh rate. |
keep-inventory-on-death | true | Keep gear on death during a match. |
auto-respawn | true | Skip the death screen; respawn instantly at team spawn. |
auto-start-players-per-team | 0 | Auto-start once both teams reach this count (0 = manual only). |
arena-defaults:
| Key | Default | Meaning |
|---|---|---|
captures-to-win | 3 | Score target. |
match-duration-seconds | 600 | Clock length (10 min). |
capture-radius | 6.0 | Blocks to grab the flag / score at base. |
flag-return-seconds | 15 | Dropped-flag auto-return timer. |
min-players-per-team | 1 | Needed to start. |
max-players-per-team | 0 | 0 = unlimited. |
flag:
| Key | Default | Meaning |
|---|---|---|
carrier-glow | true | Carrier glows in team colour (visible through walls). |
neutral-banner-color | WHITE | DyeColor of the neutral banner at centre / when dropped. |
Integration & Stats
ShardsSMPv2 integration
CTF hard-depends on ShardsSMPv2 and talks to it only through the public EventPolicy SPI:
Statistics (MySQL)
Stats reuse ShardsSMPv2's database pool via the ShardsDatabaseService SPI — there's no DB config in CTF. CTF creates its own ctf_* tables and writes off-thread. If the DB is down, stats disable and matches still play.
What gets recorded: only naturally completed matches that actually started — capture target hit, time up, or forfeit. Admin /ctf stop and server shutdown are not recorded.
Troubleshooting
| Symptom | Likely cause / fix |
|---|---|
| "Only players can use this command" | You ran an arena-build command from console — those need a player's location. Run them in-game. |
| save says incomplete | One of the six required points isn't set — the message lists which. Set it, then save again. |
| "world-mismatch" | You set points across different worlds. Place every spawn/base/flag/bounds in one world. |
| Match won't start ("not enough") | Each team needs ≥ min-players. Lower it via /ctf arena set min-players or add players. |
| No stats rows appear | DB unreachable (check the ShardsSMPv2 startup log), or the match was /ctf stop-ped / didn't complete naturally. |
Testing (temporary)
Internal — delete this section after validation. Goal: prove the full gameplay loop end-to-end and confirm a ctf_matches row is written. Needs 2 players (default min-players is 1, so a 1v1 works).
1. Build a quick test arena (in-game)
/ctf arena create testarena # stand on each spot, then: /ctf arena set spawn red /ctf arena set spawn blue /ctf arena set base red /ctf arena set base blue /ctf arena set flag # the centre /ctf arena set bounds 1 # one corner /ctf arena set bounds 2 # opposite corner /ctf arena set captures 1 # 1 capture = quick test /ctf arena save
2. Run it
- Sanity check:
/ctf listand/ctf info testarena - Both players:
/ctf join testarena(different teams) - Start:
/ctf start testarena— watch the countdown - Verify: flag banner on carrier's head, team-colour glow, sidebar score/timer, out-of-bounds teleport, death keeps gear & costs no SMP life
- Grab the centre flag, carry to your own base → with
captures 1the match ends immediately
3. Confirm the stats write
Creds are in ShardsSMPv2/config.yml.
SELECT id, arena, winner, red_score, blue_score, end_reason, duration_seconds, ended_at FROM ctf_matches ORDER BY id DESC LIMIT 1; SELECT uuid, name, team, result, captures, grabs, kills, deaths FROM ctf_match_players WHERE match_id = (SELECT MAX(id) FROM ctf_matches); SELECT name, matches, wins, captures FROM ctf_player_totals;
Expect one new ctf_matches row (end_reason = captures), a per-player row, and updated totals.
4. Edge paths & cleanup
- Time-out:
duration 30, let the clock run out →end_reason = time - Forfeit: one whole team
/ctf leavemid-match →end_reason = forfeit /ctf stopmid-match → no row written (by design)- Clean up:
/ctf stop testarenathen/ctf arena delete testarena