Add optional web jukebox: vote for arena music tracks via a small HTTP API
Build / build (push) Successful in 1m19s

This commit is contained in:
Michael Burgess
2026-08-07 11:46:43 -04:00
parent a29f359009
commit bdb18f9952
10 changed files with 475 additions and 8 deletions
+54
View File
@@ -57,6 +57,7 @@ work fine from console.
| `/blockparty leave` | Leave your current arena |
| `/blockparty arenas` | List arenas (alias of `list`) |
| `/blockparty stats [player]` | View your or another player's stats |
| `/blockparty musicvote` | (Only if the jukebox is enabled) get a one-time code to vote for the next track on the jukebox web page |
## Permissions
@@ -204,6 +205,59 @@ stop/replay-from-the-start rather than a true mid-track pause/resume — vanilla
API has no seek/resume-from-position, so each "resume" restarts the track from the beginning.
It's stopped entirely at match end, arena disable, or plugin shutdown.
### Jukebox (web-based track voting)
Optional: let players vote for an arena's music track from a web page, live, instead of (or as
a live override to) the fixed `music.track`. **Off by default** — enabling it opens a real HTTP
port on your server. Config:
```yaml
jukebox:
enabled: true
bind-address: 127.0.0.1
port: 8642
allowed-origin: "*"
vote-code-minutes: 10
tracks:
- "MUSIC_DISC_PIGSTEP|Pigstep"
- "MUSIC_DISC_CAT|Cat"
# ... id|label pairs; "id" must be a valid Bukkit Sound enum name
```
**How it works:**
1. A player runs `/blockparty musicvote` in-game and gets a short numeric code (valid for
`vote-code-minutes`). This is the only way to get a code — it proves you're a real player on
the server, without needing any separate account/password system on the web page.
2. On the voting page, they enter the code plus their arena and pick a track. Each vote is a
simple HTTP `POST /api/vote?arena=<arena>&code=<code>&track=<id>` — the plugin resolves the
code back to their player UUID, so re-voting just changes their pick rather than adding a
duplicate.
3. The plugin re-checks the current vote leader every time music resumes after a floor-wipe
pause, so the crowd can change the track between rounds within a match, not just before it
starts. Votes for an arena are cleared when it returns to `WAITING`.
4. `GET /api/tracks` lists the configured, valid tracks; `GET /api/arenas` lists each arena's
state, current track, and live vote tally, for the page to render.
**Security model and requirements — read before enabling:**
- This is a **plain, unauthenticated-by-default HTTP API** on your server. `bind-address:
127.0.0.1` (the default) means it's only reachable from the same machine — you must put a
reverse proxy (Caddy, nginx, Cloudflare Tunnel, etc.) with a real TLS certificate in front of
it to expose it to the internet safely. Do **not** set `bind-address` to `0.0.0.0` and forward
the raw port directly without TLS in front of it.
- A web voting page is normally served over HTTPS (e.g. a published page); browsers block an
HTTPS page from calling a plain `http://` address ("mixed content"), so the API being behind
HTTPS isn't optional if you want a hosted page to reach it — it's required.
- The only "auth" is the short-lived numeric code from `/blockparty musicvote`; anyone who
obtains a valid code (e.g. a player shares it) can vote as that player until it expires.
There's no rate-limiting on the HTTP endpoints — treat this as a fun, low-stakes feature, not
a hardened public API.
- `allowed-origin` sets the `Access-Control-Allow-Origin` response header; tighten it from `*`
to your actual voting page's origin if you want to restrict which sites can call it.
- Changes to any `jukebox.*` setting require a full server restart to take effect — the HTTP
server isn't restarted by `/blockparty reload`.
### Reload behavior
`/blockparty reload` re-reads `config.yml`, `messages.yml`, and every arena file. Arenas