### 🔑 A permission for every action, and screens built from them
A player either had the player screen or did not. `cdisc.player` opened all of
it 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 — and
permissions.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.
Optional dependencies
Plasmo Voice
Any compatible version
Simple Voice Chat
Any compatible version
Developer information
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle.
maven { name = "Modrinth"; url = "https://api.modrinth.com/maven" }