feat: refuse to enable when Set Homes v1 is installed alongside - #58
Merged
Conversation
Both plugins declare /sethome, /home and /delhome. v1 declares them as primary names while we declare them as aliases, and SimpleCommandMap never lets an alias displace anything, so v1 takes all six whatever the load order. Homes created after an upgrade would land in v1's homes.yml while /homes read our database, and neither plugin logs a word about it. The guard runs as the first statement of onEnable, before any directory or config is written, so a refused boot leaves the server exactly as it was and v1 keeps serving its commands.
This was referenced Aug 17, 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.
Closes #53. First of the five sub-issues split out of #41.
What changed
onEnablenow checks, as its very first statement, whether a plugin named exactlySetHomesis loaded. If one is, it logs a severe block and disables us.Nothing of v1's is touched and the server keeps running v1 exactly as it did the day before. The block names the jar to move out of
plugins/, says to keep it rather than delete it so a rollback stays possible, and gives/import-homes sethomesas the step to run once it is gone.Why refuse rather than warn
With both jars in
plugins/, Bukkit loads both happily and the command set splits along a line no player can see. Measured twice on Paper 1.21.4 on 2026-08-16:/sethome,/home,/delhome,/uhome,/home-of,/setmax/homes,/blacklistSimpleCommandMap.registerlets a primary name displace an existing alias but never lets an alias displace anything. v1 holds the primaries and we hold the aliases, so v1 wins whatever the load order./sethome shopwould write to v1'shomes.ymlwhile/homesopened our menu without it, and neither plugin logs anything about the clash. A warning that can be ignored costs players their homes; refusing to start costs a restart.The alternatives are recorded on #41 and were rejected: disabling or unloading v1 from our
onEnable, moving v1's jar ourselves, and winning the names with primary declarations plusloadbefore.Notes for review
initConfigand there is no config to read yet./sethomestwo:sethomeas a stopgap. That form only reaches us while we are enabled, so under a refusal there is nothing to fall back to.SetHomesV1ClashTestboots MockBukkit by hand instead of extendingServerTestBase, because v1 has to be registered before ouronEnableruns and the base loads the plugin in its own@BeforeEach.max-homescaveat, and restructuring the numbered list.Verification
MockBukkit: 371 before, 377 after,
Failures: 0, Errors: 0, Skipped: 0.Two tests were watched failing before the code existed. The other four passed on first run, so the guard was broken four ways to prove each one, then restored byte-identical:
equalsIgnoreCaseinstead of exact matchtheNameMatchIsCaseSensitivestartsWithinstead of exact matchaPluginWhoseNameOnlyStartsWithSetHomesIsNotV1createDirectories()andinitConfig()moved above the guardaRefusedBootCreatesNothingInOurDataFolderVerified in game on the local Paper 1.21.4 server with the real
SetHomes-1.3.0.jar, both directions: with v1 present we refuse and print the block while v1 carries on, and with v1 removed we enable normally. The boot log also confirms Bukkit loads every plugin before enabling any, so the lookup finds v1 even though we enable first.