🎵 CDisc Music
Turn any track from the internet into a real music disc. Put it in a jukebox and everyone nearby hears it through proximity voice chat: the closer you stand, the louder it gets.
YouTube, Spotify, SoundCloud, Yandex Music, VK, TikTok, Twitch, Discord attachments, your own music folder, and more.
No API keys, no tokens, no accounts. Install it and it plays. Keys still work if you have them, but nothing needs them.
📥 Requirements
- Simple Voice Chat or Plasmo Voice. One is enough; with both installed CDisc plays through both, so players on either mod hear the same jukebox, and players with both mods hear it once.
- Spigot, Paper or Folia, 1.20 or newer. One jar for all three.
Optional: WorldGuard for protecting jukeboxes in regions, PlaceholderAPI for placeholders.
Put CDisc and the voice plugin into plugins/ and restart. Players need the matching voice-chat client mod to hear the music.
🚀 Quick start
Hold any music disc and run:
/cdisc create never gonna give you up
Pick a track from the list in chat. The disc in your hand now carries that track, with its name and author in the tooltip. Put it in a jukebox, and it plays from the jukebox itself, in sync for everyone in range.
More ways to make a disc:
/cdisc create https://youtu.be/dQw4w9WgXcQwrites a link straight to the disc/cdisc create sc:lofi hip hopsearches SoundCloud (yt:sp:ym:vk:work the same way)/cdisc create local:rain.mp3plays a file fromplugins/CDisc/local, with Tab completion/cdisc disc playlist <link>writes a whole playlist: drop blank discs into the window and each gets a track
A disc is an ordinary item from then on: carry it, trade it, store it in a chest.
✨ Features
💿 Jukeboxes and the player screen
- Crouch at a playing jukebox to see a progress bar with the track and its time, then right-click it to open the player. Without crouching, a right-click takes the disc out as usual.
/cdisc sneaklets each player choose how crouching works. - The player screen: play / pause, seek ±5 s or type an exact timecode, previous / next, repeat (off, whole queue, one track) and shuffle. On 1.21.6+ it opens as a real window with sliders and buttons; older versions and Spigot get the chest screen.
- A queue of 42 discs per jukebox, played one after another. Choose what happens to a finished disc: it stays, it is ejected, or it moves to the end.
- Crossfade: the end of one disc blends into the next, with no gap between tracks.
- Nothing is lost: queues survive restarts and crashes, a playing jukebox resumes where it stopped, and breaking or burning a jukebox drops a jukebox that still holds every disc. Placing it again puts the queue back.
- Live streams from Twitch and YouTube play for as long as the broadcast runs.
- Parrots dance to CDisc discs just as they do to vanilla ones.
📡 Sound
- True proximity audio: the music comes from the jukebox and fades with distance.
- Beacon range boost: build a beacon pyramid under a jukebox and raise its range from the player screen. Bigger pyramids allow more range.
| Pyramid level | Extra range |
|---|---|
| 1 | +16 blocks |
| 2 | +32 blocks |
| 3 | +64 blocks |

- Speaker groups: link up to 8 jukeboxes into one group and they play the same track in sync. Each speaker can be set to stereo, mono, the left channel or the right one, at its own volume. Good for a club, an arena or a town square.
- Carry a jukebox: pick a playing jukebox up without stopping the track, and the music follows you, through portals too. With
/cdisc player scoreboardthe lyrics go to your sidebar, and everyone else reads them over your head. - Two volumes: one for everyone around the jukebox, and one for whoever carries it.
- Goat horns:
/cdisc createwith a goat horn in hand records a short sound onto it, up to 15 seconds by default. Blowing the horn plays it through voice chat.
🎤 Lyrics over the jukebox
- Timed lyrics float above a playing jukebox, line by line, from free lyrics databases.
- Each player chooses what they see: the words, the words with the track and time, the words with the time, the track and time, the time alone, or nothing. Left and right click on the lyrics button in the player screen step through the views, or use
/cdisc lyrics. - Your own look:
/cdisc presetsets colours, size, opacity, line count, shadow, fade and slide, with a live sample in front of you. Everyone reads the hologram their own way, and/cdisc preset share <player>offers your look to a friend. - Server presets: admins make named looks with
/cdisc admin presetsand hand them to players, to a selector, or to everyone as a default. Optionally forced, so nobody can change them. - Live chat: on a Twitch or YouTube live stream, the stream's chat takes the place of the lyrics.
🎙️ Broadcasts (experimental)
⚠️ Experimental. Broadcasts are new and may still have bugs. If something goes wrong, please report it on GitHub, ideally with a
/cdisc admin logslink.broadcast.enabled: falseinconfig.ymlswitches them off.
/cdisc create broadcast:Name makes a disc that plays no music: in a jukebox it goes live. Its host adds up to six microphones. A handheld one can be passed from player to player; a block microphone hears everyone standing near it. Voices come out of the jukebox and every speaker linked to it, so a stage or a radio station is one disc away.
📁 Your own music folder
- Drop audio files into
plugins/CDisc/localand they are discs:local:with Tab completion, played straight from disk with nothing fetched. - A
.jsoncfile beside a track gives it its own name, volume, permission and lyrics./cdisc admin local-files-config <file>edits all of it in a window. /cdisc admin download <link or search>saves a track into the folder from in game, from YouTube, Spotify, a direct link or a search, so it keeps playing whatever happens to the original.
🛠️ For server owners
- A permission for every action: pause, skip, seek, queue, carrying a jukebox, lyrics and more, all set in
permissions.yml. Screens hide the buttons a player may not use. Limits for players who are not staff: a cooldown, the longest allowed track, live streams on or off, allowed and blocked hosts. - WorldGuard: a jukebox inside a region answers only the region's members. The
cdisc-jukeboxflag opens a region's jukeboxes to everyone, or closes them to members too. - A settings window:
/cdisc admin configedits every config file in game (Paper 1.21.7+). - Diagnostics:
/cdisc admin doctorshows which sources work and which are missing something, and/cdisc admin logsuploads the log with that report for a bug report, with keys and tokens hidden. - Updates itself: new releases from Modrinth or GitHub are downloaded and installed when the server stops. This can be turned off.
- 7 languages: English, Russian, Ukrainian, German, Spanish, Hebrew and Arabic. Each player reads their client's language, or you pin one for the whole server. Your own translation drops into
languages/. - PlaceholderAPI:
%cdisc_track%,%cdisc_position%,%cdisc_progress%and more for the nearest jukebox a player can hear. - API: other plugins can listen to
TrackStartEvent,PlaybackStopEventand the cancellableDiscCreateEvent, and askCDiscApiwhat a jukebox is playing. - Upgrades keep your settings: every config file is brought up to date from the new jar, your changes stay, and the old file is kept as
.old.
🌍 Sources
| Source | Prefix | Needs |
|---|---|---|
| YouTube | yt: (or no prefix) |
nothing |
| Spotify | sp: |
nothing; keys only make search use Spotify itself |
| SoundCloud | sc: |
nothing |
| Yandex Music | ym: |
nothing |
| VK Music | vk: |
nothing |
| TikTok | links, or tt: + video number |
nothing |
| Twitch, Mixcloud, Reddit | links | nothing |
| Discord attachments | links | nothing (Discord's links expire after about a day) |
| Your music folder | local: |
nothing |
| Any direct audio link | links | http: true in sources.yml |
A search shows a list to pick from; add :10 at the end for more results. Albums and playlists open too.
Why no keys are needed
YouTube is read directly first. When YouTube refuses the server, as it does for many hosting addresses, CDisc asks its public backend, which fetches the track from its own address. The same backend reads Spotify, Yandex Music and VK links without any tokens. It is on by default; sources.yml turns it off.
Keys and tokens in tokens.yml are still read if you add them: Spotify client keys, Yandex Music and VK tokens as a fallback when the backend cannot be reached, a YouTube po-token, and an outgoing proxy. None of them are required.
⌨️ Commands
| Command | What it does |
|---|---|
/cdisc create <link or search> |
Write a track onto the disc or goat horn in your hand |
/cdisc disc clear |
Turn the held disc back into a normal one |
/cdisc disc playlist <link> |
Write a playlist onto blank discs |
/cdisc disc convert |
Convert a disc made by pv-addon-discs |
/cdisc player <pause \| play \| next \| previous \| seek \| repeat \| queue \| info> |
Control the jukebox you are looking at or carrying |
/cdisc player scoreboard |
Lyrics in your sidebar while you carry a jukebox |
/cdisc lyrics <view> |
Choose what you see over jukeboxes |
/cdisc preset |
Your own hologram look; share <player> offers it to someone |
/cdisc pair <create \| add \| remove \| dissolve \| channel \| volume \| list> |
Speaker groups |
/cdisc sneak <toggle \| release \| off> |
How crouching at a jukebox works for you |
/cdisc messages |
Turn "Now playing" messages on or off |
/cdisc admin <reload \| doctor \| download \| logs \| config \| presets \| local-files-config> |
Server tools; they run from the console too |
📊 Stats
All Versions
+ Add Version| Name | Game version | Platforms | Published | Downloads | Actions |
|---|---|---|---|---|---|
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
| 18h ago | 1 | ||||
|
R
1.7
|
18h ago | 1 | |||
|
R
1.6
|
18h ago | 1 | |||
|
R
1.5
|
18h ago | 1 | |||
| 18h ago | 1 | ||||
|
R
1.4
|
18h ago | 1 | |||
|
R
1.2
|
18h ago | 1 | |||
|
R
1.1
|
18h ago | 1 | |||
|
R
1.0.1
|
18h ago | 1 |
- New graphite player heads: Advanced settings, speakers, the queue and every Back button are heads too
- Player screen themes: Dark or Legacy (the old heads and vanilla items), switched in Advanced;
gui-themesets the default - CDisc discs no longer show the vanilla song name under their own lore
- Disc lore is translated into the maker's language and shows track length and a live-stream marker
- Developer API: control jukeboxes, their queues, screens, discs and player settings from other plugins
- Developer API on Maven through JitPack
- Tracks a plugin queues are locked discs that never leave the jukebox as items;
api.allow-discs-in-queuemakes them ordinary discs
- Own audio engine: LavaPlayer, youtube-source and LavaSrc removed, jar 41 MB to 3 MB
- NBT-API removed
- Own readers for YouTube, SoundCloud, Twitch, Spotify, Yandex Music, VK Music, HTTP and local files
- Faster Spotify discs
- Sources removed: Mixcloud, Reddit, Vimeo, Bandcamp, OC ReMix, Soundgasm, PornHub
- Settings removed:
youtube.clients,youtube.log-client-failures,youtube.fast-create,youtube.probe-timeout-seconds - Lyrics off the server thread, far lower load
- Lighter crouch progress bar
- Files saved off the server thread
- Parrots dance to CDisc discs
- Lyrics button: next and previous view, shift opens the look
- Busy jukeboxes can't become speakers
/cdisc disc converthas its own permission- Fixed: duplicated carried jukeboxes
- Fixed: Folia queue saving
- Fixed: explosions silencing jukeboxes
- Fixed: non-CDisc items in the queue
- Fixed: late-cancelled jukebox breaks
- Fixed: vanilla disc lost on break
- Fixed: failed discs copied into the queue
- Fixed: hopper-inserted discs not playing
- Fixed: blank disc after moving it while loading
- Fixed: YouTube player detection
- Fixed: seeking through the YouTube backend
- Fixed: seek jumping back
- Fixed: Spotify tracks matched to another song by the same artist
- Fixed: startup error in the console when no voice plugin is installed
- Broadcasts:
/cdisc create broadcast:Namemakes a disc that plays no music. In a jukebox it goes live, and its host — whoever made the disc — or an operator adds up to six microphones from the Broadcast button. A handheld microphone is heard only from its holder, can be passed on or put back in the jukebox, and returns to the host pasthandheld-range; a block microphone hears a player as far as their voice carries, quieter with distance. Voices reach the jukebox and its paired speakers through Simple Voice Chat and Plasmo Voice.broadcast.enabledin config.yml switches it off. - Crossfade: the next disc in a queue is loaded ten seconds before the end and the last seconds of both are blended.
crossfadein config.yml sets the length, 0 turns it off, and each jukebox can turn it off from Advanced or the dialog's options. - Server hologram presets:
/cdisc admin presets add <name>makes a named look in the/cdisc presetwindow,set <name> <players> [true|false]gives it to players or a selector,unsettakes it back andremovedeletes it. Given without force it is a starting point players can still change; forced, it is all they see.default <name|none> [true|false]gives it to everyone else, players who join later included. Edits reach everyone at once. Needscdisc.admin.presets, operators by default. - The player screen is two rows: controls on top, Advanced, the lyrics and exit below. Speakers, volume, beacon range, carrying, track messages, the dialog switch and crossfade moved to Advanced, and each player's last screen is opened again next time.
- PlaceholderAPI placeholders
%cdisc_...%describe the nearest jukebox a player can hear; other plugins getTrackStartEvent,PlaybackStopEvent, the cancellableDiscCreateEventandCDiscApi. youtube-sourceno longer plays tracks: after the direct read only the backend is asked. It still lists searches and playlists.- The crouch progress bar goes away once the player is out of earshot, and a jukebox that is playing, holds a disc or has a queue can no longer be paired as a speaker.
- Parrots within three blocks of a jukebox dance to CDisc discs as they do to vanilla ones, and stop when playback ends.
- Players given a server hologram preset without force keep their own look: the Return my own look button in
/cdisc presetbrings it back, and editing the preset turns it into their own./cdisc admin presets unsetalso returns it. - The lyrics button in the player screen: left click shows the next view above jukeboxes, right click the previous one, and shift+click opens your own hologram look.
- /cdisc admin logs now has its own permission, cdisc.admin.logs.
- log-upload: false in config.yml turns it off.
Note: by mistake, cdisc.admin used to grant /cdisc admin logs too. So anyone given cdisc.admin just for /cdisc admin doctor or reload could also upload the server log to a public link. Now it takes cdisc.admin.logs.
- Breaking a playing jukebox no longer starts the vanilla disc sound.
- WorldGuard support: jukeboxes in a region answer only its members (flag cdisc-jukebox).
- Yandex Music and VK Music without a token
- TikTok links working again
- Per-file settings for the music folder
- Faster Spotify matching
- Live stream chat in place of lyrics
- Errors go to the plugin log
- YouTube discs start faster.
- Tracks blocked in the server's country go straight to the backend.
- Search also shows videos only the backend can play.
- A region-blocked track falls back to another upload of the same song.
- Fewer requests to the backend.
- Each player chooses what floats over jukeboxes with
/cdisc lyrics. - A jukebox someone else has open shows you a smaller screen instead of refusing.
- Resetting a hologram look asks for confirmation.
- Direct links into the server's own network are refused.
http: trueno longer re-enables sources that are switched off.- Updates are also checked on GitHub Releases.
- YouTube now asks one source at a time: the direct read first, then the backend, youtube-source last. YouTube links work on servers where youtube-source is blocked.
- The direct read is always on;
youtube.sabronly adds a SABR retry. - New
proxy.addressin sources.yml sends all plugin traffic through an HTTP proxy. The login goes in tokens.yml./cdisc admin reloadapplies changes without a restart. - New
/cdisc admin logsuploads the server log with the doctor report to mclo.gs and returns a link to attach to a GitHub issue. Keys and tokens are hidden. - The settings window (
/cdisc admin config) is on by default. - New
debugin config.yml shows in the console which source each track came from. - Removed
/cdisc admin ytsetup.
- Add a settings window at /cdisc admin config
- Play SoundCloud through the backend proxy
- Record short sounds onto goat horns
- Seeking in long YouTube videos is now instant.
- A failed audio frame no longer silences a jukebox.
- Spotify playlists and albums work without keys; YouTube links with a playlist are read as playlists.
- Spotify search without keys falls back to YouTube.
- Local files with non-Latin names play correctly.
- New releases download and install themselves when the server stops.
- The backend is on by default, and the proxy turns on by itself on servers in Russia. Turning either off is respected.
- A disc taken out of the queue no longer keeps playing from the jukebox as a copy.
- Give a new lyrics hologram its preset size from the first line
A player either had the player screen or did not.
cdisc.player opened all ofit at once: pause, skip, seek, volume, the queue, and picking the jukebox up to
carry it away. Half of it could not be handed out.
Every action now carries a node of its own —
cdisc.player.pause,cdisc.queue.add, cdisc.lyrics.toggle, thirty-eight of them — andpermissions.yml holds one rule per action instead of one default per command:
``
yml
actions:
player:
pause: [somegroup.admin, somegroup.mod]
portable: op
repeat: '!somegroup.muted'
beacon: false
`
A rule is true, false, op, notop, the name of a permission, the name of
one with a ! in front for whoever has *not* got it, or a list of any of those,
and one matching line in the list is enough. true, false and op are set as
the default of the node itself, so a permission plugin can still overrule them
for a single player; a rule that names other rights is a second way in rather
than a way to lose one.
The screens are drawn from the same answers. Someone who may not carry a
jukebox is not shown the button for it, someone who may not change the volume
does not get the slider in the dialog, and a queue that may be read but not
edited refuses the disc rather than swallowing it. The commands answer per
subcommand, so /cdisc player pause and /cdisc player next are separate
questions.
Nothing has to be rewritten by hand: the old defaults block is carried onto
the new rules the first time the plugin starts, and the old node names keep
working as parents over the actions they used to cover, so a grant of
cdisc.player in LuckPerms still reaches all of its pieces.
### 🎨 Everyone reads the hologram their own way
A preset was meant to be personal, and a player who set one did get an extra
hologram drawn to their own taste — but that copy was never hidden from anybody
else. Two players with presets at the same jukebox each read three sets of words
at once: their own, the other's, and the jukebox's, stacked in different colours
over the same block.
Every reader now sees the words their own preset asks for and nothing else. One
hologram is put up per look actually in use among the players within 80 blocks
of the jukebox, so a crowd that never touched /cdisc preset still shares a
single entity between them, and each hologram is invisible to everyone outside
its own group. Nobody nearby means nothing is spawned at all. The words over the
head of a player carrying a jukebox follow the same rule: bystanders read them in
their own colours and line counts while the carrier reads the sidebar.
Fade length and slide come from the preset now, like every other setting, and
are no longer greyed out in the screen: they used to be the jukebox's to set,
because one hologram had to animate one way for the whole crowd.
- The look stored on a jukebox is gone.** It was the one place where a style
could be put on everybody else's screen, which is the thing this release stops.
Right-clicking the lyrics paper opens your own preset instead, the "Put my look
on this jukebox" button and the cdisc.lyrics.look permission are removed — the
node is named in the console when permissions.yml is brought up to date — and a
style already written into a jukebox block is ignored. config.yml keeps its
part: it is the look a player reads until they change it.
### 🚪 A carried jukebox kept playing on the other side of a portal
Walk into the Nether with a jukebox in hand and the music was gone. The carrier
still heard it, since what reaches the person holding one is a channel of their
own, but everyone else hears it from an invisible entity the jukebox is tied to,
and an entity does not follow a player into another world. It stayed behind: put
the jukebox down over there and nobody heard a thing, pick it up again and only
the carrier did.
That entity is now raised again where the carrier is standing and the sound is
built around the new one, with the volume, the distance, the speaker settings
and the carrier channel put back on it. The old one is closed only once the new
one is playing, so the track does not stop while they are swapped.
### 💬 The words over a carrier stopped trailing behind them
The words above someone carrying a jukebox were moved once every five ticks
while the sound they belong to follows every tick, so the text lagged a step
behind the player and swung back into place a moment later. It now follows on
the same beat as the sound, and it stands perfectly still while the carrier
does.
### ⏱ CDisc stopped taking a sixth of the server thread
A profile of a running server put the plugin at ~15% of the main thread with a
handful of jukeboxes playing. Nearly all of it was work that did not need doing.
Asking a block a question in Bukkit is not a read, it is a snapshot: the whole
block entity is written out to NBT and parsed back. Two of those were happening
for every playing jukebox every few ticks, one to ask whether the words are
shown over it and one for the speaker settings. Both answers are now read once
and kept until they change, and both are dropped when the jukebox stops or the
plugin is reloaded. The hologram pass also leaves early when nothing is playing
at all.
Following a player who carries a jukebox cost about as much again. Every tick it
asked whether the carrier still has the thing by copying the whole inventory out
and reading the data of every jukebox in it to compare an id; the handle is now
looked for in the slot it was found in last time, and the inventory is swept
only when it is not there, which is the tick it gets dropped, stashed or handed
over. The entity that carries the sound was teleported every tick whether or not
the player had moved, and a teleport is a tracker update for everyone nearby, so
it now moves only when the carrier does.
The same server afterwards, with all of that running at once: 0.8% of the main
thread, about a twentieth of a core. The two profiles are not the same minute of
play, so read the shape of it rather than the exact ratio.
### 🔴 YouTube live streams stopped after five seconds
A live broadcast played for exactly five seconds and then stopped, with nothing
in the console to say why.
Live has no length and no size: it is handed out as a chain of five-second
segments, and the address in the player response serves the one segment that is
current. CDisc read that address the way it reads an ordinary video, got its
five seconds, reached the end of the stream and finished the track. As far as
the player was concerned the song was over, so there was nothing to report.
Live is now recognised as live and read segment by segment for as long as the
broadcast runs. The address is fetched afresh on every start, so a stream that
drops comes back on a current link rather than an expired one, and the audio is
taken from an MP4 format because that is what the segment reader can parse. The
track is finally marked as a stream, which brings with it everything the plugin
already does for streams: reconnection, LIVE in place of a running time, no
downloading, and the allow-live permission.
Writing a disc from an ordinary YouTube video could fail outright on servers
that check a track before writing it: the check plays a copy, and a track read
straight from YouTube could not be copied. It can now.
### 🟣 Twitch channels loaded but played nothing
A channel came up with its title and its name on the disc, and then silence.
Two things were wrong. Links to twitch.tv were being sent to an address on the
backend that answers 404 for every channel, live or not. And Twitch has since
moved its streams to fragmented MP4, which the library's reader, written for
MPEG-TS, finds no audio in.
Twitch links now go to the plugin's own reader. It takes the initialisation
segment named in the stream's playlist, which is where the description of the
audio lives, plays the fragments that follow it, and falls back to the old
MPEG-TS path for a channel that is still served that way. Choosing the quality
and waiting on new segments is left to the library, which is sound.
### 🔊 Both voice plugins at once
A server with Simple Voice Chat and Plasmo Voice both installed had to pick
one, and CDisc refused to start until it was told which. That was the wrong
question: the two mods' users are different people, so choosing a backend was
choosing which half of the server heard nothing.
Both are now used together. One jukebox is still decoded once, and a source is
opened in every installed voice plugin, so whichever mod a player brought, the
music arrives. voice-backend: auto does this by itself when both are present;
multi asks for it explicitly, and naming simplevoicechat or plasmovoice`still pins it to one.
Players who have *both* mods installed would hear the track twice, a few
milliseconds apart — a flanging smear worse than either feed alone. So each
listener is handed to a single backend and filtered off the others, reworked
once a second as people connect and disconnect their voice mod. Nobody is
filtered off a backend unless another one is already reaching them.
Simple Voice Chat starts later than Plasmo does, on its own startup event, so
it joins a broadcast that may already be playing: anything mid-track gains its
Simple Voice Chat source on the spot, with the distance, speaker settings and
carrier it missed replayed onto it.
The cost is one Opus encode per playing jukebox per voice plugin. The track
itself is decoded once regardless.
### 🎤 Lyrics stopped piling up over the jukebox
Leave a song playing, walk away, come back, and the words over the jukebox were
there twice. Then three times, then six: a stack of frozen lines from different
points in the track, overlapping into an unreadable block that nothing short of
a restart would take down.
A display entity reports itself invalid the moment the server stops ticking the
chunk it stands in, which is what a jukebox's chunk does as soon as the last
person walks far enough off. The hologram read that as "gone" and put up a
replacement over the top of the one still hanging there — and read it the same
way when the time came to take a hologram down, and so took nothing down. Either
mistake alone leaves one more copy per trip away and back, for as long as the
track keeps going round.
It now asks whether the display has actually been removed rather than whether it
happens to be ticking, takes the old one down before putting any replacement up,
and once a minute looks over the jukeboxes that are playing for words it is no
longer holding on to and clears them. The same mistake was in the words above a
carried jukebox and in the sample shown while a hologram's colours are being
chosen; both go with it.
A server with Simple Voice Chat and Plasmo Voice both installed had to pick
one, and CDisc refused to start until it was told which. That was the wrong
question: the two mods' users are different people, so choosing a backend was
choosing which half of the server heard nothing.
Both are now used together. One jukebox is still decoded once, and a source is
opened in every installed voice plugin, so whichever mod a player brought, the
music arrives.
voice-backend: auto does this by itself when both are present;multi asks for it explicitly, and naming simplevoicechat or plasmovoicestill pins it to one.
Players who have *both* mods installed would hear the track twice, a few
milliseconds apart — a flanging smear worse than either feed alone. So each
listener is handed to a single backend and filtered off the others, reworked
once a second as people connect and disconnect their voice mod. Nobody is
filtered off a backend unless another one is already reaching them.
Simple Voice Chat starts later than Plasmo does, on its own startup event, so
it joins a broadcast that may already be playing: anything mid-track gains its
Simple Voice Chat source on the spot, with the distance, speaker settings and
carrier it missed replayed onto it.
The cost is one Opus encode per playing jukebox per voice plugin. The track
itself is decoded once regardless.
### 🎤 Lyrics stopped piling up over the jukebox ([Issue #7](https://github.com/valkdzx/CDisc-Issues/issues/7))
Leave a song playing, walk away, come back, and the words over the jukebox were
there twice. Then three times, then six: a stack of frozen lines from different
points in the track, overlapping into an unreadable block that nothing short of
a restart would take down.
A display entity reports itself invalid the moment the server stops ticking the
chunk it stands in, which is what a jukebox's chunk does as soon as the last
person walks far enough off. The hologram read that as "gone" and put up a
replacement over the top of the one still hanging there — and read it the same
way when the time came to take a hologram down, and so took nothing down. Either
mistake alone leaves one more copy per trip away and back, for as long as the
track keeps going round.
It now asks whether the display has actually been removed rather than whether it
happens to be ticking, takes the old one down before putting any replacement up,
and once a minute looks over the jukeboxes that are playing for words it is no
longer holding on to and clears them. The same mistake was in the words above a
carried jukebox and in the sample shown while a hologram's colours are being
chosen; both go with it.
### 💿 Discs stopped going missing out of jukeboxes
A jukebox's queue lived in memory and nowhere else. The world stores the one
disc physically shown inside the block; the other 41 cells existed only for as
long as the server was up, so a restart — or a crash, or a
/reload — deletedevery disc anybody had loaded into a jukebox, with nothing to get them back
from. Nobody watching it happen could have guessed the cause: the discs were
put somewhere the plugin itself displayed them, and they were gone the next
morning. [Issue #6](https://github.com/valkdzx/CDisc-Issues/issues/6)
Queues are written to
plugins/CDisc/queues.yml now, next to the file thatalready remembered what was playing. They are saved a couple of seconds after
anything changes and again on the way out, and read back the first time
something asks after a jukebox — so a queue comes home when a player walks up
to it, rather than everything at once on startup. A jukebox that was mid-track
picks its queue back up along with its position, without the disc it was
playing turning into two.
Two other ways a disc could disappear are closed with it:
- A break somebody else refused.** The break handler ran at normal priority
left the queue drained, the record cleared, and a jukebox full of the owner's
discs lying on the ground for whoever was standing there. It now runs last
and not at all on a refused break.
- Queues nobody had emptied.** Every jukebox anyone had ever opened stayed in
is looking at that jukebox's screens.
### 🔁 And the ways a disc could become two
A hopper under a jukebox empties it — a jukebox has been a container since
1.21 — and only a right-click ever told the queue that its disc had physically
left. The disc went into the hopper and stayed in the queue as well, so
breaking the jukebox afterwards dropped a second one. No timing and no trick
involved: a hopper, a jukebox, and time.
Double-clicking a disc in your own inventory gathers every matching stack in
the window onto the cursor, the queue cells included. That is the one way into
those cells that never arrived as a click on one, so nothing wrote the change
back — the disc left the screen while the queue still held it, and the next
repaint put it back into the cell it had just come out of.
### 🎵 The playlist screen no longer eats discs on a reload
Blank discs handed to the playlist writer are held by the screen rather than
left in the window, because it pages. They were held in memory alone, so a
/reload or a shutdown with that screen open destroyed every one of them: bythe time the player is kicked, the close that hands them back has nobody left
to run it. The screens are shut on the way out now, which returns them the
ordinary way. The discs are also handed over a tick after the window closes
rather than during it, so a client tearing that window down doesn't miss them.
### 📻 Carried jukeboxes
A carry that ended with no item to fold its discs into simply discarded them,
and it takes no unusual settings to end one that way — logging out with the
jukebox on your cursor rather than in a slot is enough, because the search for
it only ever looked at inventory slots. The discs come back as a jukebox at the
carrier's feet now, or where it was picked up from if they have already gone.
Servers that raise
portable-jukebox.max-per-player above 1 had two more.Putting one jukebox down dropped *every* carry its owner had, leaving the
others as items nothing answered to — never settled, never handed back. Logging
out or dying settled only the most recently picked up, and left the rest
playing to an empty world.
Shuffle is kept when a carried jukebox goes back down somewhere else — it was
the one setting the move forgot.
## 1.8.1
### 💾
/cdisc admin download takes what /cdisc create takesIt used to accept a direct link to an audio file and nothing else, which left
the one thing an operator actually wants to keep — the track a player just made
a disc of — as the one thing it could not fetch.
It now takes the same queries disc creation does, and resolves them the same
way, because it is the same call: a **YouTube link** goes straight off YouTube
where that works, through SABR where it does not, and through the backend for
the videos YouTube wants an account for — an age gate is a download like any
other now. A **Spotify link** is matched on its ISRC to the recording the label
uploaded, rather than to whatever a title search ranks first. A **search** shows
the same clickable list, and the line you pick is the file you get. A direct
link to a file is still fetched exactly as it was, name after it and all.
The file is named after the track —
Artist - Title — and its extension comesfrom what actually arrives, since the same recording is webm off one road and
m4a off another. Live streams are refused: there is no end to download to.
The console can answer a search now as well as start one, since
/cdisc adminruns there and a list you cannot pick from is not an offer. It prints the same
numbered lines and takes
/cdisc pick <number>.A download arrives in about a second rather than in the time the track lasts.
Two things were making it take exactly as long as listening would. The
n on adirect YouTube link was left as it came: an untouched one is not refused on a
media URL the way it is on the streaming endpoint — it is served, at roughly
the speed the track plays at. It is descrambled now, the same as the SABR
endpoint's always was, which also gives playback the headroom it never had. And
the fetch asks for a byte range instead of opening a plain GET, because a
request that names a range is a download to the far end rather than a stream,
and is answered at the speed of the line. A server that will not be asked that
way is fetched the old way instead.
- The whole
admingroup runs from the console now, not justdoctorand
download: /cdisc reload works from a startup script, a scheduler or aremote panel without anybody having to log in first.
ytsetup is the oneexception — it ends in a clickable link and then waits for the person who
asked to come back with a code, and the console can do neither. Everything
outside
admin still needs a player, since it needs a disc in a hand or amenu on a screen; asked from the console, those now say so and point at what
does work, instead of the bare "Only players can run this." Tab completion
offers the console only what it can actually run.
- A disc pushed into a jukebox by a hopper no longer plays twice — the custom
Suppressing the vanilla sound depends on the jukebox being known as ours
before vanilla announces the disc, and the only thing that marked it was a
player's right-click; a hopper right-clicks nothing, so the announcement had
nothing to be cancelled by. Marked on the item transfer now, which covers
hoppers, droppers and hopper minecarts. The mark is checked again the tick
after, so a transfer that doesn't land can't leave a jukebox that silently
swallows the next ordinary record.
### 📎 Files from Discord are a source of their own
A link to a file attached to a Discord message plays now without switching
http on, and the disc it makes says what it is: **Discord** as the artist,the file's own name as the track. Before this it was either refused —
httpis off by default, and it has to be, since it opens every URL on the internet
at once — or, on a server that had switched it on, written to a disc reading
"Unknown artist — Unknown title", because an upload carries no tags and
LavaPlayer fills both fields with a stand-in that looks like real metadata.
Pasting a link out of Discord is the one thing players actually do with a
direct file, so it is
discord: true in sources.yml by itself: one host,not the whole internet. A file that *does* carry tags keeps them — the naming
only steps in where there was nothing.
- The name comes from Discord rather than from the link**, because the link
так похуй [tRAmPLYjbGg].mp3 is served from .../tRAmPLYjbGg.mp3, with theRussian words and the brackets gone, and the whole name handed back in the
Content-Disposition header instead. So anything not written in Englishexists only in that header, and reading the URL — which is what this did at
first — gets an English-alphabet stub of the name and nothing else. It is one
request, made once, when the disc is written rather than when it plays; if it
fails or the link has expired, the name out of the URL is still written.
One thing worth knowing, and it is Discord's rather than ours: those links
expire about a day after they are copied. The
ex=/is=/hm= on the end isa signature with a deadline in it, and Discord answers an expired one with a
404 — which used to arrive in game as "track not found" and read as though
the file had been deleted. A link past its date now says so, and says where
to get a fresh one.
/cdisc download is how to keep one for good: the fileis fetched once and plays off the disk afterwards.
- Repeat and shuffle now survive a restart. They were held in memory only, so
resume-playback brought the track back and left the jukebox on defaults —it finished the resumed disc and stopped. They are written down beside the
position now, and restored before it, so a jukebox that was left looping is
still looping. Saved for stopped jukeboxes too: how one is set is not about
the track that happened to be in it, and losing that on every restart was the
same bug wearing a different hat.
- Age-restricted tracks now go to the backend first, whether or not it is
sources.yml. YouTube refuses them for wanting an account,which no amount of retrying from the server can supply, so the paths that
would be refused now run after the one that has one rather than before it.
The refusal is recognised on both roads — the direct SABR attempt and
youtube-source — so a server with either or neither switched on still finds
it.
### 🪟 The player screen is a real window now
1.21.6 gave servers dialogs — actual windows, with a title, text, buttons and controls. On 1.21.6 and up the player screen opens as one instead of as a chest full of items pretending to be buttons.
player-dialog: false in config.yml puts the inventory screen back.What that buys is that the screen can be shaped like what it does. Most of what an inventory has to make a button is not a verb at all: a volume is a number, repeat is one of three things, whether the words show is yes or no. Each of those was an item you clicked, with its own state written into its name and "left click louder, right click quieter" in the lore.
- Sliders** for both volumes and for the position in the track.
- A choice button** for repeat, and **tick boxes** for shuffle, the words above the jukebox, and track messages.
- A field** for typing a timecode, for when a slider is not precise enough.
- Square buttons** for what is left, which is only what actually does something — one glyph each, with the sentence in the tooltip where it belongs.
Nothing applies until Apply is pressed, and only what actually moved is written: coming here to change the volume does not also seek the track back to where it stood when the screen opened.
- No words of the song on this screen.** They belong over the jukebox, where a hologram can be as tall as it likes and everybody standing there reads them. Here they could only go above the controls — a dialog draws title, then body, then inputs, then buttons, in that order and no other — so every line of song pushed every button further down. The track name went into the title bar for the same reason.
- Controls that would do nothing are left out rather than greyed out**: no position slider on a live stream, no beacon range without a beacon under the jukebox, no speaker settings on a jukebox whose group screen owns them.
There is one cost and it is forced rather than chosen. A dialog reports its inputs only when a button is pressed, so a screen carrying them cannot be rebuilt underneath the player — every redraw would drag every slider home. So the position it shows is where the track was when the screen was drawn, and any press draws it again.
- Only this screen.** The disc queue and the speaker settings stay inventories, because both are about picking discs up and putting them down and a dialog has nowhere for an item to go. A button that leads to either closes the dialog and opens the chest.
Ignored entirely below 1.21.6 and on Spigot, which has no dialog API — those servers get the inventory screen whatever the setting says. Both screens drive the same set of actions underneath, so neither can drift away from the other.
### 💬 Switching the lyrics on says what came of it
Turning the hologram on said only that it was on. Then, quite often, nothing appeared over the jukebox — and there was no way to tell which of several reasons applied, because they all look the same from where the player is standing, which is empty air.
There is now a line in chat for each one: the words were found and the hologram is live; this track has no synced lyrics; nothing is playing yet; a live stream has no timed lyrics at all; or the jukebox is in your hand, where the words go to the screen instead of the sky.
The answer usually isn't known at the moment of the click — the first lookup for a song goes out to the lyrics databases — so it says it is looking and comes back with the outcome. The wait is dropped the moment it stops being about anything: the hologram switched off again, the queue moved on to another track, or the player left. If the databases never answer, it says that too, rather than leaving a "looking..." that never resolves.
### ⏱ The length limit applies before the choice, not after it
limits.max-track-seconds in permissions.yml was only checked at the moment a disc was written. A search offered every hit it found, including the hour-long ones, and the refusal arrived after the player had already picked one — which reads as the setting not working at all.Results now come pre-filtered: a search shows only what this player may actually write, and the count is taken after filtering, so they still get a full page rather than the leftovers of one. When a search finds things but none of them qualify, it says so, instead of claiming nothing was found and sending the player off retyping their query.
- The server's own music folder is exempt from the limits now, where it used to be caught by them.** These rules are about what players may pull in off the internet. A file under
local:was put in that folder by the admin deliberately and is already offered to everyone who can type the prefix, so its length is not a player's decision to be limited.
- The playlist screen was skipping the limit entirely.**
/cdisc disc playlisthanded out a slot per track and wrote whatever discs were dropped in, however long the track — the whole rule was one command away from being bypassed. It now offers only the tracks that qualify and says how many it left out.
Nothing changes for staff, who were never subject to these limits, or for servers leaving
max-track-seconds at 0.### 🔈 Speaker groups play as one, not as an echo
- A group's jukeboxes now leave the server on a single clock.** Standing between two of them no longer sounds like a slapback — the frame a listener gets from one speaker is the frame they get from the others, sent in the same instant from the same thread.
Plasmo Voice gives every audio source a sender of its own, a loop that waits twenty milliseconds and never quite makes up the remainder it lost. Two sources started a moment apart therefore never agree again, and the gap only widens. Capping how much each one could bank held the damage to about sixty milliseconds — audible as a doubled sound, and bought by dropping frames to stay there. Members of a group skip that machinery entirely now: their audio goes on the wire from the thread that decoded it, so there is no second clock left to drift.
The deep buffer stays where it belongs, on a jukebox playing alone, where a decoder that pauses for a moment should not leave a hole and no one can hear the delay that hides it. Simple Voice Chat was never affected — it always sent from the calling thread.
### 🧹 The console speaks English, and says less
Every message CDisc writes to the server console was in Russian, which is no use to most of the people who install it. They are all in English now.
There are fewer of them, too. Two fired on every single track and told nobody anything — one on each non-YouTube load, one on each YouTube load that worked — so a quiet track is now quiet. What is left is what somebody would act on: a failure, a fallback being taken, or a setting that needs turning on.
Player-facing text is unaffected: it comes from
languages/, and /cdisc player still accepts вкл and выкл alongside on and off.### 🔊 Speaker volume goes both ways
Left click is louder, right click is quieter. It used to be one button that only stepped up and wrapped past full round to silence, which meant nudging the volume up one notch too far switched the speaker off — and getting back to where you were took nine more clicks.
The jukebox's own volume already worked this way; the speaker settings screen now agrees with it.
### 🎵 Spotify links play, and keep their own names
- A Spotify link is matched to the YouTube video of the same recording, by ISRC.** That code names a recording rather than a song, so the remaster, the cover, the karaoke version and the sped-up edit are all told apart — which searching by title cannot do. YouTube returns the label's own upload for it, and its length agrees with Spotify's to within a second.
No mirroring source manager is involved any more. The link resolves here and then goes down the same direct road as everything else, which is also why it now plays at all: the old path handed it to youtube-source, and that no longer works.
- Two ways to resolve one, either is enough.** Spotify credentials in
tokens.yml— one request per track, the token behind it cached — or a token server that resolves Spotify links, which does the whole thing in one. With neither, the console says exactly that instead of calling it a broken link. - A match has to look like the track, not merely last as long as it.** YouTube does not answer "nothing found": a query it has no answer for is padded with whatever it has, and one such video matched a track's length to within half a second and went onto a disc as a news report. Length is now the tie-breaker it always should have been, behind the artist or the title actually agreeing.
- The disc keeps Spotify's title and artist.** An Art Track lives on an "Artist - Topic" channel, and that suffix was ending up on discs.
- Making a disc takes the same road as playing one.** It used to go straight to the libraries, which is why a Spotify link could play but not be written to a disc.
- The backend URL is honoured wherever it was written** —
sources.ymlis its home,tokens.ymlis where people put it anyway, and a bare host now finds either service's endpoint instead of guessing one and giving up on a 404.
### 🎧 YouTube plays without any of the bot-check machinery
- A client YouTube still answers the old way.** Asked as visionOS, YouTube returns every format with a direct link: no SABR endpoint, no proof of origin, no BotGuard, no
nto descramble, and nothing attested. The one thing it wants is a visitor id, and any will do — one ordinary page fetch hands one out.
- SABR stays behind it**, for what visionOS is not given — videos marked as made for kids, among others.
- Tokens become optional.**
po-tokenandvisitor-datamatter only on the SABR path now. Configure nothing and YouTube still plays. - The console names which path a track came out of**, because the two break differently: a direct link can expire or be refused from another address, while SABR can lose its attestation and answer with a minute of audio.
- YouTube is asked first now, rather than after youtube-source has failed.** The library is not even started unless the direct road comes back empty, which is why the console no longer carries a page of
All clients failedbefore every track that then played fine.
### 🔑 YouTube tokens keep themselves current
- One pair, kept current by itself.** What YouTube attests is the visitor identity — eleven characters — and not the long string that carries it. The string can be re-signed with one ordinary web request, so CDisc does that about once an hour, with no browser and no service in the middle, and writes the result back into
tokens.yml. The values there change on their own now; that is the feature.
backend-youtube-tokens.json beside it records when that last happened, so a restart installs what is already there instead of fetching anything.- The first pair has to come from somewhere.** Paste one into
tokens.yml, or pointyoutube.po-token-backend.urlat a token server. Nothing is shipped as a default: an identity baked into a release is one every install shares, and a shared identity wears out — two died inside a day while this was being built. With neither, the console says so at startup instead of half working. visitor-datawithoutpo-tokenis now a supported arrangement**, and the ordinary one. On every measurement made here the identity is what decides whether a track plays whole or stops a minute in; the token decides nothing about playback.- A pair dropped into the file from outside is picked up within half a minute** — by the token server, a cron job, or somebody with an editor — without a restart.
### 📡 YouTube's new streaming protocol is read directly
- SABR streams play.** YouTube has begun answering some requests with a response that lists every format and gives a direct link to none of them — the audio is meant to be pulled through a single endpoint by POSTing to it repeatedly, saying where playback has reached. There is no file and no byte range, so every downloader built around a URL comes away empty.
That endpoint is now read here. Turned on by
youtube.sabr in sources.yml, on by default, and only ever used for a response that has no links in it — a server YouTube still serves the old way never touches this path.It needs a visitor identity: SABR checks one on every request, and without an attested one a track plays about a minute and stops. CDisc keeps one current by itself once it has one — see above. The request is made signed-out, which is what the identity is for — an OAuth login alongside an identity earned in a private window tells YouTube two different stories about who is asking.
Seeking works. SABR has no byte offsets, but the same request returns the same bytes, so a rewind is either replayed out of the opening kept in memory or the conversation begun again from the start.
### 🐛 Fixed
- A YouTube track that resolved and then went silent now says why, and plays anyway.**
YouTube has started answering some requests with SABR: the response is complete — every format listed, audio included — but none of them carries a direct URL, because everything is meant to be pulled through a single streaming endpoint instead. youtube-source skips a format it has no URL for, skips all of them, and reports
No supported audio streams available, available types: with nothing after the colon.That message reads as *"YouTube sent us nothing"* and means the opposite, which is a long way to walk in the wrong direction — through tokens, addresses and OAuth, none of which are involved.
- The console now names it: forms, but no direct links, and neither the tokens nor the server's address are at fault.
- A SABR answer puts the Custom API ahead of youtube-source for the next ten minutes, so the tracks after it play at once instead of each one starting, failing and falling back.
/cdisc admin reloadclears the preference, since a reload is somebody having changed the very settings worth retrying. - With no backend configured, the console says so plainly rather than letting the disc die quietly.
- A jukebox left on pause keeps its disc.**
Pause it, walk off for a minute, and the jukebox came back empty-handed: no track, nothing playing, and the only way on was Play from the top and a seek back to where you left off. Local files did it too, so it was never the network.
While paused, nothing was asking the player for audio — quite reasonably, since there is none to send. But LavaPlayer reads a player nobody has asked in a minute as abandoned and stops its track out from under it. It is asked for a frame every tick now, paused or not; paused, it hands back nothing, which is exactly what pause should sound like, and the disc is still there when you come back.
## 1.8.0
- The lyrics hologram is yours now.** Every jukebox can be styled on its own, every player can carry a look that follows them, and a jukebox in your hands finally has somewhere to show its words.
### 🎨 Style the hologram
The hologram used to look one way for the whole server. Now there are three places to set it, each falling back to the next: **your own preset → the jukebox's → the config**.
- Per jukebox** — right-click the lyrics paper in the jukebox GUI.
| Colours page | Layout page |
|---|---|
| Background colour and opacity | Size and height |
| Brightness | Line width |
| Colour, opacity and formatting of the line being sung | Lines above and below |
| The same for the lines around it | Drop shadow, see-through |
| | Fade length, slide, countdown dots |
- Per player** —
/cdisc presetopens the same screen for a look that follows you to every jukebox on the server.
- A live sample while you edit** floats in front of you and disappears with the screen. Changes land a tick after the click instead of waiting for the next line to be sung.
### 🤝 Share a look
``
/cdisc preset share <player>
`
They get **[Accept]** and **[Decline]** buttons in chat, and nothing about what they read changes until they press one. What they accept is what you showed them, not whatever you moved on to afterwards.
### 📜 Lyrics for a jukebox you're carrying
A hologram needs a jukebox standing still, so a carried one had nothing to read.
`
/cdisc player scoreboard
`
The words go in **your sidebar** while you carry it, and **above your head** for everyone else. Off unless you ask for it, and the sidebar slot is handed straight back when you put the jukebox down.
### 🔊 Two volumes
A jukebox has one volume for everyone standing around it — and, while carried, a second one for whoever is holding it.
- Set the jukebox to 30 and the carrier gets 30 too, until they say otherwise
- Shift-click** puts them back on the jukebox's
- Both live in the player screen as light blocks that carry the level as their own brightness, so you can read it off the slot
### 🔀 Shuffle
A new button in the player screen. Picks the next disc at random, refusing only the one that just played.
### ▶️ The player opens on a stopped jukebox
It used to refuse unless something was playing — which is backwards at the moment you want it: the track ended and you want to start another.
- Opens on a jukebox that's playing, has a queue, still holds a disc, or is in your hands
- The transport **starts** something instead of sitting greyed out
- Right-click the air** while carrying a jukebox to open it
### 🌍 One language for the whole server
`yaml
language: auto # or ru_RU, en_US
`
auto keeps the old behaviour of following each player's client. Set a language and the server sounds like one place — console and links included, not just chat.
Translating it yourself? Drop languages/<name>.yml into the plugin folder and name it here. Missing keys fall back to English, so a half-finished file still works.
### ⚙️ Commands are seven groups instead of twelve
`
create · disc · preset · player · pair · messages · admin
`
clear, convert and create-playlist live under disc; reload, doctor, download and ytsetup under admin. **Every old spelling still works** — they're just no longer suggested, so the tab-complete list is readable.
### ✨ Smaller things
/cdisc player info tells you what's playing next/cdisc doctor reports the lyrics databases, songs cached, holograms floating and players with a presetThe progress bar is white. Red still means a live stream
### 🐛 Fixed
- The remote cipher solver was off** on any server whose
sources.yml` predated the setting — stream URLs went unsolved and it looked switched off on purpose### 📖 Documentation
The [po-token guide](https://wiki.2281273.xyz/#/youtube) now tells you to press **Show more** in DevTools — the payload is cut short above the token, and the copied text wouldn't parse. Its extractor also refuses a placeholder token instead of handing you one YouTube treats as no token at all.
- A disc duplication bug is fixed. Update.** It needed two players and a
The other half of the release is migration: discs burned by
- pv-addon-discs** can be converted to CDisc discs instead of being written
## Fixed: discs could be duplicated through a carried jukebox
The queue screen shows real discs rather than pictures of them — that is what
lets you drag one out. For as long as the screen is open, those discs exist in
two places at once, and everything around it is built to make sure only one of
those places survives.
Carrying slipped between the guards. Picking a jukebox up deliberately keeps
the music playing, so the teardown that closes these screens never ran, and the
existing guard covered the queue alone — which left room for a second player to
be in the player screen at the same time. Between the two, a jukebox could
leave the world with somebody still looking at its queue, and the discs on that
screen outlived the ones that travelled away inside it.
Three separate changes close it, and any one of them would have been enough on
its own:
- Carrying a jukebox now closes every screen it has open, the same as a track
- One player at a time on a jukebox's screens — all of them, not just the
- A screen is no longer written back to a queue that has already been emptied
- One thing changes for players:** two people can no longer have a jukebox's
any number at a time. The second person is told the jukebox is in use. This is
deliberate — any second window onto the same discs is another way for them to
be counted twice.
If your server ran 1.7 or earlier with
portable-jukebox enabled, it wasexposed. There is no way to tell from the plugin whether it was used; the discs
themselves look ordinary.
##
/cdisc convertHold a disc that pv-addon-discs wrote and run the command. It is rewritten in
place — same track, same disc, now CDisc's.
Nothing is fetched. That addon stores only the audio identifier, so conversion
is instant, works with no internet, and succeeds even for a video that has
since been taken down. Playback works from the address either way.
- What carries across.** The URL, and the track name — which that addon keeps
so a converted disc reads *Unknown* until you write it again with
/cdisc create. Discs from the earliest releases work too: their namespace wasmisspelled
pv-addon-disks, and both spellings are read.- The old data is removed rather than left alongside.** A disc carrying both
whichever reached the jukebox first.
- The host allow-list still applies.** A disc burned before CDisc was installed
allowed-hostswould refuse that URL today, the conversion is refused too.
Permission is
cdisc.create; there is no separate node, since convertingwrites a disc like any other. The create cooldown does not apply — nothing is
downloaded, so there is nothing to rate-limit.
Goat horns are not converted. CDisc has no equivalent for them, and holding one
gets a message that says so rather than "hold a music disc".
## Compatibility
Minecraft **1.20 through 26.x**, on Spigot and Paper. No configuration changes;
nothing to do beyond replacing the jar.
1.6 shipped speaker groups with a caveat: per-speaker channel and volume only
did anything on Plasmo Voice. **That caveat is gone.** Simple Voice Chat now
honours both, and a jukebox carried on Simple Voice Chat no longer breaks up
while you run.
The second headline is **search you can pick from**. A query that isn't a link
lists what it found in the chat, and you click the track you meant instead of
taking whatever came first.
Two things for server owners: **API keys move out of
config.yml into theirown file**, and CDisc gains **permissions and limits** on what a player can
make your server fetch.
## Simple Voice Chat catches up
- Per-speaker channel and volume now work.** Simple Voice Chat was handed
byte-identical sound — the settings saved to the block, showed up in the GUI,
and had nothing to act on. Each output is now encoded separately, so a pair of
speakers can split a stereo image the way it always could on Plasmo.
- Stereo* folds to mono there, because Simple Voice Chat has no stereo stream to
genuinely different, which is what splitting an image across two speakers
actually needs.
- A carried jukebox stays clean.** Carrying one used to make the music break up
zero distance the direction from listener to source is undefined, so it swung
on every step. The carrier now gets a channel with no position at all — steady
in both ears — while everyone else keeps hearing it from where you're standing.
The swap overlaps in both directions, so picking a jukebox up and putting it
down have no gap and no click.
This costs one Opus encode per playing output where Simple Voice Chat
previously had none. It is the price of telling two speakers apart. It also
removes an old penalty: a global
volume below 100 used to force a fullre-encode of every track, and no longer does.
## Search you can pick from
``
/cdisc create yt:daft punk one more time
`
A query that isn't a link now **lists what it found in the chat** — number,
title, artist, length — and every line is clickable. Click one and it's written
to the disc in your hand.
Ask for a specific number of results by putting it on the end:
`
/cdisc create yt:one more time:10
`
Five by default, ten at most. A trailing :something is only read as a count
when it really is a number, so yt:nightcore: reloaded stays one query, and
links aren't parsed for it at all.
The disc records the **track's own address**, not your query. A disc written
from a search keeps playing the track you picked even if the same words return
something else next year.
Three rules keep the list honest: it belongs to whoever searched, so someone
else clicking it does nothing; choosing consumes it, so one search writes one
disc; and it expires after three minutes rather than quietly writing a track
you'd forgotten about.
## Keys live in their own file
config.yml held Spotify secrets, Yandex tokens and VK credentials in among
the ordinary settings — the one file you'd paste into an issue report or hand
to somebody helping you debug.
Configuration is now four files:
| File | Holds |
| --- | --- |
| config.yml | Plugin settings |
| sources.yml | Which sources are on, and their options |
| permissions.yml | Rights and limits |
| tokens.json | **Every key and secret** |
- Nothing to do on update.** The split happens on first start: the new files
are written, then the moved sections are removed, and the original is kept
beside them as config-before-split.yml.bak. Nothing is deleted until the
replacements are safely on disk.
tokens.json is the one file to keep out of screenshots and bug reports.
## Permissions and limits
Every command now sits behind a node, registered with the server at startup so
LuckPerms and friends can see them by name:
`
cdisc.create cdisc.create.playlist cdisc.clear
cdisc.player cdisc.pair cdisc.portable
cdisc.messages cdisc.admin
`
- The defaults match how CDisc behaved before it had permissions**, so updating
changes nothing until you change something.
Then there are limits, and they exist for a specific reason: /cdisc create
makes *your server* fetch a URL that a *player* chose.
| Setting | Default | What it does |
| --- | --- | --- |
| create-cooldown-seconds | 5 | Wait between two creates by the same player |
| max-track-seconds | 0 | Longest track allowed on a disc; 0 is unlimited |
| allow-live | true | Whether live streams may go on a disc |
| allowed-hosts | empty | Fill it in and only these hosts are permitted |
| blocked-hosts | empty | Hosts refused outright |
A leading www. is ignored and subdomains count, so youtube.com also covers
music.youtube.com. Search queries aren't URLs and neither list touches them —
they can only ever reach the source they name.
Refusals always say why, in chat. cdisc.admin ignores all of it.
## Playback survives a restart
`yaml
resume-playback: true
`
Jukeboxes pick up where they left off — same track, same second — instead of
going silent until somebody re-triggers them.
Resuming waits for the **chunk to load**, so a jukebox in an empty corner of
the map costs nothing until a player walks over. A jukebox that was **paused**
stays paused, since resuming it would be starting music nobody asked for. Live
streams come back at the live edge rather than a stale position.
## Sound settings for a jukebox on its own
The channel, volume, name and particle settings introduced in 1.6 were reachable
only through the speaker-group screen, which meant a single jukebox couldn't be
turned down without pairing it to something first. **Sound** now opens the same
screen from the player GUI on any jukebox.
## The update checker actually tells you
Three separate reasons it stayed quiet, all fixed:
- It **only checked at startup**. A release published while your server was
already up was invisible until the next restart. It now re-checks on a timer,
every six hours by default (update-checker.interval-hours).
- It **hid releases over their version list**. A build that didn't name your
exact Minecraft version was treated as not existing. Versions are now matched
by family, so a server on 26.2.build.56 matches a release listing 26.x.
- Notices are **warnings**, so they stand out in a console instead of scrolling
past among the info lines.
## Documentation
CDisc has a documentation site: 19 pages in English and Russian, with search,
per-page contents and a dark theme. Everything below the surface of this
changelog is written up there properly.
## Smaller things
/cdisc create with a playlist link tells you how many tracks it left behind, and points at create-playlist.
- Source settings moved to
sources.yml, so turning YouTube's fallback API on no longer means editing the same file as your speaker-group limits.
- A source with no key is skipped with a line in the console at startup, rather
than registering itself and failing later.
## Fixes
- An unconfigured Spotify registered itself anyway.** The shipped placeholder
was the literal text null, which every check treated as a real client ID —
so the source came up with null` as its credentials and failed on useinstead of standing aside.
## Compatibility
Minecraft **1.20 through 26.x**, on Spigot and Paper.
- Per-speaker channel and volume now work on both voice backends**, which
left: a *stereo* setting folds to mono on Simple Voice Chat, since it has no
stereo stream. Left, right and mono behave identically on both.
One track, many jukeboxes. **Speaker groups** wire several jukeboxes together so
they play the same disc from their own positions, in sync, each with its own
channel and its own volume — a left speaker and a right speaker across a room,
or a whole club covered by one queue.
The second headline is **
/cdisc create-playlist**: write an entire playlist toa stack of blank discs in one pass instead of one disc at a time.
## Speaker groups
Open the player GUI on a jukebox and hit **Speaker group**. Name the group in
chat, then pick free jukeboxes nearby out of a list — the picker shows every
unpaired jukebox within range of the main, with its distance.
The jukebox you started from becomes the **main**: it holds the discs, the
queue and the player, and it is the only one that decodes the track. The rest
are **speakers** — they emit that same audio from where they stand. Two
jukeboxes playing the same disc separately drift apart within seconds; a group
does not, because there is only ever one decode.
- Speakers are locked.** No discs go in, no queue, no player GUI, no ejecting —
refused rather than silently playing over the group.
- Ownership.** Only the player who created the group may change its jukeboxes,
owner never comes back doesn't become permanently unbreakable. Turn the whole
protection off with
speaker-group.protect-members: false.Breaking a **speaker** removes it from the group. Breaking the **main**
dissolves the group entirely and every jukebox becomes ordinary again.
A jukebox belongs to **one group at a time**. Try to pair one that is already
taken and the refusal tells you which group is holding it, so two people
building nearby can't quietly fight over the same block.
- A paired jukebox cannot be carried** — not even by the owner. Take it with
says so instead.
Limits, all in
config.yml under speaker-group:| Setting | Default | What it does |
| --- | --- | --- |
|
enabled | true | Off switch for the whole feature ||
max-distance | 64 | How far a speaker may sit from the main, same world only ||
max-per-group | 8 | Members including the main ||
protect-members | true | Owner-only changes and breaking |The distance limit isn't arbitrary: a speaker emits from an entity in its own
chunk, so one across the world would only play while somebody stood there
keeping that chunk loaded — a speaker that works sometimes. Raise it for a very
large build, not for a relay network.
Commands, if you'd rather not use the GUI:
``
/cdisc pair gui
/cdisc pair create <name>
/cdisc pair add <name> | remove | unlink | dissolve
/cdisc pair tag <name>
/cdisc pair channel <stereo | mono | left | right>
/cdisc pair volume <0-100>
/cdisc pair info | list
`
## Settings for each speaker
Click any member in the group screen to open its own settings:
- Name** — give the speaker a tag ("Left", "Bar", "Upstairs", up to 24
characters) and it's labelled that way everywhere it appears.
- Channel** — *stereo*, *mono*, *left* or *right*. Left and right are a
genuine split of the source: the left speaker plays the track's left channel
and nothing else, the right one the right. Put them either side of a room and
the stereo image spreads across it.
- Volume** — 0 to 100 in steps of 10. **0 is a full mute**: the speaker keeps
its place in the group and comes straight back when you turn it up.
- Particles** — the note particles above that jukebox, on or off.
- Make this the main** — promotes a speaker; playback stops for the swap.
- Unlink** — that one jukebox leaves the group and goes back to normal.
Everything is stored on the jukebox itself and survives restarts.
## Everything stays in sync
Three jukeboxes standing near each other used to drift apart badly — the
overlap made the music louder and smeared it. Each audio source runs its own
sender, and a one-second buffer let a source that fell behind stay behind
forever.
Group members now run on a **60 ms buffer** instead, which is short enough that
nothing can lag behind audibly, and it's applied live — pair a jukebox in the
middle of a track and it drops into step without a restart.
## Playlists, one command
`
/cdisc create-playlist <playlist URL>
`
CDisc reads the playlist and opens a screen with one slot per track, paginated
if it's a long one. Fill the slots with **blank music discs**, close the
screen, and every one of them is written at once — the action bar counts the
discs as they're stamped.
Fewer discs than tracks is fine: you're told how many tracks had no disc, so
you can top up and run it again. Discs that won't fit in your inventory drop at
your feet rather than vanishing.
/cdisc create with a playlist link used to write **only the first track and
silently discard the rest**. It now writes that first track and warns you how
many more the playlist held, pointing at create-playlist.
## Encoding moved to the voice server
Technical, but it's what the rest of this release stands on. CDisc used to have
LavaPlayer produce one already-encoded stereo stream and hand the same bytes to
everybody, so the channel count was fixed for every listener at once. It now
hands raw audio to Plasmo Voice and lets **each source encode its own**, which
is what makes per-speaker mono, left and right possible at all.
## Smaller things
- Speaker groups are reachable from the player GUI**, not only through the
disc queue.
- Every button in the player GUI has its own icon** — no two share a texture
any more. Speaker group is a jukebox, Take it with me a note block, Channels
a brewing stand, Track messages a bell.
- New: Track messages** (the bell). The "now playing" line on the action bar
is now **per player** — turn it off if you don't want it and everyone else
keeps theirs. Also /cdisc messages [on|off]`.- Setting confirmations go to the action bar** instead of the chat, so
- A way back** — the group screen has a back button to the player.
- Dropped the per-track "loaded successfully" line from the console.
## Fixes
- Carrying a jukebox with a full queue disconnected you.** A jukebox holds
block and left it there. Pick it up again with a couple of dozen discs inside
and CDisc tried to write more than 64 KB into a field that cannot hold it,
which drops the connection. The leftover copy is now cleared when the jukebox
is placed — it was also a latent way to duplicate discs — and an oversized
snapshot is refused with a console warning instead of a kick.
- Speaker tags were stored but never actually displayed; members read
- The group screen had no way back to the player.
## Compatibility
Minecraft **1.20 through 26.x**, on Spigot and Paper.
Speaker groups themselves work on both voice backends. **Per-speaker channel
and volume, and the tightened sync, need Plasmo Voice** — on Simple Voice Chat
a group plays from every member, but the settings have nothing to act on.
Two things in this release will matter to you before anything else: **YouTube
plays again**, and **CDisc no longer disconnects players on Minecraft 26.x**.
Everything else is new features on top.
## YouTube playback fixed
YouTube tracks could fail to play at all, with the console filling up with
Expected decoding to halt and every client reported as failed.CDisc was only ever asking YouTube clients that hand back a format LavaPlayer
cannot decode, while the ones that work were never asked. It now asks those
first, so tracks play immediately instead of failing.
As a safety net, a track that still can't be played is retried through the
fallback API rather than being written off. That needs
sources-config.youtube.fallback-api: true.## Chat and action bar rebuilt on the server's own API
On Minecraft 26.x, **every message CDisc sent disconnected the player** —
action bars, hints, the update notice, the YouTube setup link. The library that
built those packets is no longer maintained and supports Minecraft only up to
1.21.11.
CDisc now hands the text to the server and lets it build the packet, so a
future protocol change can't break it the same way. Colours, hover text and
clickable links are unchanged — and on 26.x the "now playing" action bar works
for the first time.
## Portable jukeboxes
Pick up a jukebox **without stopping the music**. Open the player GUI and hit
- Take it with me** — the block goes into your inventory, note particles rise
and the jukebox is restored exactly as it was, still playing, still queued.
Drop it, die with it, stash it in a chest or log off, and playback stops and the
jukebox becomes an ordinary item again — with every disc still inside it.
While you are carrying it, the music is sent **straight to you** rather than
played from a point in the world. Carrying a sound source on top of your own
ears is what made the audio break up as you ran; sending it directly removes
the problem instead of masking it. Anyone nearby keeps hearing the jukebox
positionally, from wherever you are standing, exactly as before.
Picking the jukebox up and setting it back down are **seamless** — the two
audio paths overlap across the swap, so there is no gap and no jump in volume
at the moment it changes hands.
Configurable under
portable-jukebox: off switch, how many one player maycarry, particle rate.
## Jukeboxes now hold their discs
Breaking a loaded jukebox used to spit out every queued disc as a separate item
— up to 42 at once, in a single tick. The discs now ride **inside the jukebox
item**, so a break drops exactly one item however full the queue was, and
placing it back restores the queue. Easier on the server, and impossible to lose
half your discs down a hopper.
The same applies everywhere discs used to spill: ejecting one by hand, or an
explosion going off next to a jukebox, no longer empties the queue onto the
ground.
## New
/cdisc player commandsFull playback control without the GUI, for the jukebox you're carrying or
simply looking at:
``
/cdisc player gui | queue
/cdisc player pause | play | next | previous
/cdisc player seek <MM:SS | +seconds | -seconds>
/cdisc player repeat [off | track | queue]
/cdisc player status | info
`
repeat with no argument cycles through the modes. status toggles the
progress boss bar. /cdisc seek is replaced by /cdisc player seek, which also
takes relative offsets.
## Reaching a jukebox that isn't playing
A jukebox holding discs but playing nothing was a dead end — there was no way to
get them back out. **Sneak + right-click with an empty hand** now opens its
queue, and clicking a disc there starts playing it.
## Faster disc creation
/cdisc create no longer waits on a playability check before saving the disc;
the source is picked on first play instead. Creation is several times quicker.
Revert with sources-config.youtube.fast-create: false.
## Update notifications
CDisc checks Modrinth on startup and tells you in console — and operators in
chat, with a clickable link — when a newer release is out. Only releases that
support the Minecraft version you're actually running are offered. Turn it off
with update-checker.enabled: false.
## Anonymous statistics
CDisc now reports to [bStats](https://bstats.org/plugin/bukkit/CDisc%20Music/32754):
server counts, versions, and which features get used. No player names, UUIDs,
IPs, track titles or search queries are ever sent. Opt out with metrics: false`.## Fixes
- Duplication**
- Ejecting a disc while sneaking dropped it on the floor while the queue kept a
- A carried jukebox whose queue ran out duplicated its last disc when placed
- Stashing, dropping, dying with or logging off holding a carried jukebox could
- Portable jukeboxes**
- The audio of a carried jukebox broke up while running, and was worst in first
there is nothing left to break up.
- Swapping between carried and placed left an audible gap in one direction and
- A carried jukebox put back down read as empty: the music played but no GUI
- Moving a jukebox to a new spot stopped its queue advancing — the current track
- Stashing a carried jukebox in a chest left the music playing.
- The queue GUI wouldn't open for a carried jukebox at all.
- General**
- The progress boss bar switched itself off between tracks.
- An explosion next to a jukebox stopped the wrong one's playback.
- The YouTube setup link stopped being clickable on 1.21.5 and newer, after
- A failed track no longer buries the console in the same stack trace three
## Compatibility
Minecraft **1.20 through 26.x**
Direct audio for a carried jukebox needs **Plasmo Voice**. On Simple Voice
Chat a carried jukebox still plays and still follows you — it just stays
positional, as it did before.
- Added**
- 🔊 Plasmo Voice support (alongside Simple Voice Chat)
- 📀 Disc queue system — up to 42 discs per jukebox, played-disc policy (keep / eject / move to end) and repeat (off / queue / track)
- 🎛️ Reworked in-game player GUI: prev / next track, seek ±5s, repeat modes
- 📊 Now-Playing boss bar with a progress bar (sneak near a jukebox)
- 🔦 Beacon-pyramid range boost for audible distance
- Fixed**
- YouTube links with a playlist/mix part (
&list=...&index=...) no longer fail to load — only the linked track is played - Disc duplication when ejecting a disc or breaking a jukebox mid-queue
- Vanilla disc sound no longer leaks when the queue advances to the next track
- Boss bar keeps updating when you look away from the jukebox
- tiktok
- mixcloud
- ocremix
- pornhub
- soundgasm
Important! It doesn't work 100% because DuncteBot has been archived since November 26, 2023.
https://github.com/DuncteBot/skybot-source-managers