Repository navigation
Conversation
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Decoded notes now share one copy of each instrument and sample name, cutting a 7,500-note project from about 1.1 MB to 0.2 MB of heap. Saves check the legacy single-project layout once per owner instead of parsing the selected file on every save and checkpoint. The sample-name pattern is compiled once, and publishing checks audibility without building a full timeline. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cached projects already match their files except for a final take that is still saving or whose write failed. Disconnects and shutdown now retry only those, instead of rewriting every cached project and risking the shutdown timeout. A disconnect evicts a current project from memory. "Take saved" is announced only for finished takes, not for these saves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The library, /music projects, the 36-project limit and deletion now use project summaries (title, tracks, length, pending slot) instead of decoding every project on the server thread. Summaries are cached in a per-owner library.index file keyed by each project file's size and modification time. save() updates it, and listing rebuilds missing, stale or damaged entries, so files changed outside the studio stay correct. With 36 projects of 7,500 notes, listing drops from about 1.9 s and 40 MB to under 5 ms. The first listing after upgrading builds the index once. The delete confirmation keeps a summary rather than the whole project, and rejects the deletion if the summary changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Published editions are kept forever because discs reference them, and republishing over a recorded disc added a new file every two clicks. Edition IDs are now derived from their content, so republishing unchanged music reuses the earlier edition. A configurable publish-cooldown-seconds (default 30, 0 disables) limits how often a player can publish. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Jukebox playback reads the cheap block type every tick and the record, which copies the block state and item, once a second. Ejecting or breaking the jukebox still stops playback immediately. - The jukebox click handler checks the block type before getState(), so right-clicking chests no longer copies their inventories. - ItemsAdder station lookups resolve their reflective methods once instead of on every right-click and menu refresh. - Saving serializes the project once for both copies. - Startup removes studio-*.tmp files left by an interrupted write. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 11, 2026
A pending take inherits its track's volume and mute, so reviewing a take recorded over a muted or zero-volume track played nothing for the whole song while holding a session. The take review now plays the take audibly with the saved backing. Listening to a mix or a single track with nothing audible is refused instead of running silently. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every save and checkpoint wrote the whole project twice: once to its per-project file and once to projects/<owner>.yml as the selection. The selection is now a small "selected" file holding the project ID in the owner's folder, which halves project storage and write volume. Existing data migrates once per owner on first access: the newer of projects/<owner>.yml and its per-project copy becomes the project file, the selection pointer is written and the old file is removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Format 1 wrote every note as a five-item YAML list, about 77 bytes per note. Format 2 lists each track's instrument and sample names once and stores each note as one text line of "<ticks since the previous note> <instrument> <sample> <volume> <pitch>". Format 1 files remain readable and are rewritten in format 2 the next time they are saved. With a 6,000-note project (TF Main limits) on a development machine: - File size: 459 KB to 132 KB (about 22 bytes per note). - Save: 31 ms to 7 ms. Load: 45 ms to 4 ms. - Loading an edition for a jukebox: 40 ms to 3 ms. - Republishing unchanged music: 72 ms to 5 ms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One unreadable project file (invalid YAML, an unknown format, the wrong owner or ID, or a name that is not a project ID) made listing fail, so the player could not open the library, create a project or even delete the broken one. A damaged active project also blocked creating or opening another. Unreadable files are now skipped and logged once, and left on disk for an administrator. The library index remembers them until the file changes, so they are not reparsed on every listing. A damaged active project or selection leaves the player without an active project. An unreadable legacy projects/<owner>.yml is moved to <owner>.yml.damaged. Disk access errors are still reported to the player as before. A checkpoint test now waits for the save to finish instead of reading the file while it is replaced, which can fail on Windows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every volume, mute, tempo, metronome, title, keep or discard change wrote the whole project on the server thread. Edits now apply to the cached project at once and are queued on the existing ordered writer, after the final take and any older edit, so the latest write always holds the latest project. Edits no longer wait for a take to finish saving. Creating, opening and deleting projects still wait for queued writes, because they read or remove project files. Opening a project now only rewrites the small selection file instead of both projects, and creating one no longer rewrites the previous project unless its last write failed. A failed write keeps the change in memory, tells the player and is retried by the next change, every minute, on disconnect and on shutdown, instead of only on disconnect or shutdown. Shutdown waits up to 30 seconds for queued writes instead of 5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The publish cooldown limited how often a player could publish, not how many editions piled up: small mix changes could still add one file every 30 seconds, kept forever. A new max-editions-per-day setting in studio.yml (default 20, 0 disables) limits new editions per player in any 24 hours, tracked in editions/<owner>.log. Republishing music that is already published does not count, and a refused publication keeps the disc. Editions now leave out muted, zero-volume and empty tracks and silent notes, which playback never emits. Muting a silent track therefore reuses the same edition. Republishing compares the existing file's bytes instead of parsing it again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With an ia.* station configured and ItemsAdder missing or disabled, every right-click on any block tried to load the ItemsAdder classes by reflection, failed with ClassNotFoundException, and also searched the block for entities. Stations now match nothing until ItemsAdder is enabled. Methods missing from the installed ItemsAdder version are also remembered instead of looked up again on each click. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A hopper taking a recording disc from a jukebox left the song playing until the next once-a-second record check. The listener now stops it as soon as the disc moves, like breaking or ejecting does. The cheap item and inventory type checks run first, since hoppers move items constantly. Notes already sent when a jukebox stops are left to end on their own: each note is short, and stopping a sound by name would also cut a live instrument playing the same sample nearby. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The studio only ran on TF Dev, with one test song that will be removed, so there is no data to carry over. Remove the one-time move from projects/<owner>.yml to the per-project layout and the reader for format 1 notes. Format 1 files written by 3.3.0 are now reported as an unsupported format and skipped like any other unreadable file. The library index is also written in format 2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes bugs and performance problems found while reviewing the multitrack studio released in v3.3.0, focused on server-thread stalls, memory use and disk growth. One commit per topic.
Correctness
Server-thread time and memory
/music projectsand the 36-project limit read a per-ownerlibrary.indexof project summaries instead of decoding every project (36 projects of 7,500 notes: about 1.9 s and 40 MB down to under 5 ms). Delete confirmations load only the requested project to check its full content.getState().ia.*station without ItemsAdder made every right-click on any block fail a reflective class lookup.Disk
projects/<owner>/selectedholds its ID.publish-cooldown-seconds(default 30) andmax-editions-per-day(default 20, per player in any 24 hours, tracked ineditions/<owner>.log) instudio.yml; 0 disables either. Republishing existing music does not count, and a refused publication keeps the disc.studio-*.tmpfiles left by an interrupted write.Behaviour changes
projects/<owner>.yml) are not read; format 1 files are logged and skipped. Older plugin versions cannot read format 2.studio.ymluse the defaultmax-editions-per-dayuntil the key is added.Validation
mvn clean verify: 326 tests passed; 100% instruction and branch coverage, with no production exclusions.🤖 Generated with Claude Code