Add bookspy and unify spy modes - #59
Merged
Merged
Conversation
Paldiu
approved these changes
Aug 4, 2026
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.
Adds /bookspy and unifies the spy on/off flags into a single shared mode enum so all four spies filter the same way.
/signspy is in this PR because release/v26.9-sirius forked from prod just before the PR merged, so signspy does not exist on this branch. The first four commits are that feature with two conflicts resolved for sirius:
PlayerData.saveTo()dropped since sirius removesConfigSavablefromPlayerDataand persistence now lives inGenericPlayerRepository;ranks.ymldropped in favor ofranks.json.The last commit is the new work:
SpyMode
player/CommandSpyMode.javais replaced byplayer/SpyMode.java(OFF,OPS,ADMINS,ALL) with a singleshows(boolean senderIsAdmin)used by CommandSpy, PotionSpy, SignSpy, and BookSpy.All four commands take the same argument and tab complete the same values
[ops | admins | all | off]. A bare/signspyor/bookspyenablesOPS, so admin edits stay out of the way by default. A bare/cmdspyor/potionspystill enablesALL, unchanged behavior.Unknown modes are now rejected instead of disabling the spy. The lenient parser is deliberately named
fromStoragerather thanfromString:EnumArgumentResolverprefers a staticfromStringover its own lookup, so naming it that would make e.g./signspy opssresolve toOFF./bookspy
BookSpylistens toPlayerEditBookEventand reports edits in the same shape as SignSpy, with a per page line-level diff:shroomp edited book (page 14) +'the new line', -'the line that went away'
shroomp edited book (pages 2, 4, 7) +'first'[...] (and 3 more)
shroomp signed book 'Abolish OP Rights' [Read Book]
Buttons are
[See Edit | Read Book], or just[Read Book]for a book's first write, where both would open the same page.See Editopens at the first edited page;Read Bookopens the whole book from page 1. Paper'sopenBookcan't be told which page to open at, soSee Edithands over a copy sliced to start at that page.Closing a book without changing it is ignored, as is a new blank draft. Signing is reported separately. Output is capped with
[...]and(and N more)markers so a large book can't flood chat.Storage
The
playerstable gainspotion_spy_mode,sign_spy_mode, andbook_spy_mode(TEXT/VARCHAR(16), default'off') across the SQLite, MySQL, and PostgreSQL adapters, withaddColumnIfMissingmigrations for existing databases. The booleanpotion_spycolumn is gone.Legacy yaml still imports correctly:
PlayerData.loadFrommaps the oldpotion_spyandsign_spybooleans toall, and that is the pathYamlMigrationService.migratePlayersuses.The spy mode getters null-coalesce to
OFFbecausePlayerListsnapshotsPlayerDatathrough Gson, which allocates the object without running field initializers, so a snapshot written before a mode existed comes back with the field unset.