
CDisc Music
Плагин CDisc Music позволяет превращать любые треки с YouTube, Spotify, SoundCloud и других сервисов в музыкальные диски для Майнкрафт. Диски играют из проигрывателя с эффектом приближения через голосовой чат - чем ближе игрок, тем громче звук. Работает с Simple Voice Chat или Plasmo Voice.
Список изменений
Changelog
1.8.1
💾 /cdisc admin download takes what /cdisc create takes
It 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 comes
from 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 admin
runs 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 a
direct 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 justdoctoranddownload:/cdisc reloadworks from a startup script, a scheduler or a remote panel without anybody having to log in first.ytsetupis the one exception — 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 outsideadminstill needs a player, since it needs a disc in a hand or a menu 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 track and the vanilla record sound at the same time, over each other. 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 — http
is 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
hasn't got it. Discord reduces a filename to ASCII on the way into the URL:
так похуй [tRAmPLYjbGg].mp3 is served from .../tRAmPLYjbGg.mp3, with the
Russian words and the brackets gone, and the whole name handed back in the
Content-Disposition header instead. So anything not written in English
exists 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 is
a 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 file
is fetched once and plays off the disk afterwards.
-
Repeat and shuffle now survive a restart. They were held in memory only, so
resume-playbackbrought 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 switched on in
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 playlist handed 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 n to 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.
