Developer PartyAddon Integration - Atlasroar/WandererZ GitHub Wiki
PartyAddon Integration — Methodology
This page documents why and how Globox1997/PartyAddon was merged directly into WandererZ in v2.2.0, following the same playbook as the JobsAddon, RpgDifficulty, and Tiered merges.
Why this merge was different
PartyAddon is a small player-party/group mod (invite, join, leave, kick, shared XP), but unlike Tiered — whose LevelZ coupling was a single optional compat mixin — PartyAddon shipped a hard modImplementation 'maven.modrinth:levelz:1.4.11+1.20.1' dependency. Its core feature (sharing XP among group members when any member picks up a LevelZ XP orb) directly imports net.levelz.access.PlayerSyncAccess, net.levelz.entity.LevelExperienceOrbEntity, and net.levelz.init.KeyInit, and one of those import points is a @Redirect mixin targeting a literal bytecode descriptor string, not just a plain Java import.
Both mods also:
- target the same Minecraft version (1.20.1) and Yarn mappings
- use a fully disjoint Java package (
net.partyaddon.*), a clean sibling tonet.wandererz.*/net.jobsaddon.*/net.rpgdifficulty.*(and distinct from Tiered's non-net-rooteddraylar.tiered) - use a disjoint resource namespace (
assets/partyaddon) — PartyAddon ships nodata/folder, so it has no datapack-configurable content and needed no new "Datapack Creation" wiki section
Step-by-step methodology
- Inventory the tree. Cloned PartyAddon's
1.20branch — a small addon (29 Java files: group manager, party screen/HUD, networking, Clumps/Xaero's World Map compat). Grepped everylevelz-related reference (~25 matches across 8 files) to scope the compat rewrite. - Copy source wholesale, keeping
net.partyaddonas the package name, and copy all resources (assets/partyaddon,partyaddon.mixins.json). - Rewrite the LevelZ compat points:
PartyAddonMain.isJobsAddonLoaded+.isLevelZLoaded→ collapsed into a singleisWandererzLoadedfield checkingFabricLoader.isModLoaded("wandererz"). Both upstream checks collapse to the same post-merge condition, so keeping two separate always-identical booleans added nothing.PartyAddonMixinPlugin— theFabricLoader.isModLoaded("levelz")guard controlling whetherLevelExperienceOrbEntityMixin/LevelZServerPlayerEntityMixinapply was updated to check"wandererz". The unrelatedisModLoaded("xaeroworldmap")guard forGuiMapMixin/ControlsHandlerMixinwas left untouched (genuinely optional third-party compat).LevelExperienceOrbEntityMixin(inmixin/compat/) —net.levelz.access.PlayerSyncAccess/net.levelz.entity.LevelExperienceOrbEntityimports repointed tonet.wandererz.*, and the@Redirect's literal bytecode descriptor target stringLnet/levelz/access/PlayerSyncAccess;addLevelExperience(I)Vrepointed toLnet/wandererz/access/PlayerSyncAccess;addLevelExperience(I)V(same descriptor-string-fix pattern as the TieredSkillInfoScreenMixinmerge).PartyScreen—net.levelz.init.KeyInitimport repointed tonet.wandererz.init.KeyInit.LevelZServerPlayerEntityMixin— class name and itsaddLeaderLevelZExperience/addLevelZExperienceinterface method names (onGroupLeaderAccess) were left unchanged: these are PartyAddon's own API surface describing what the method does (distribute LevelZ-style XP), not a reference to a LevelZ class that moved — same reasoning as JobsAddon'slevelZXPMultiplicatorfield being left unrenamed.PartyAddonConfig.distributeLevelZXP— this is a previously-shipped PartyAddon config field (unlike Tiered's brand-newlevelzReforgeModifier), so the field name was left as-is to avoid breaking existing PartyAddon configs on upgrade, following the JobsAddon precedent rather than the Tiered one. Only the@Commentdoc-string and the lang-file display label were rebranded to "WandererZ".- Dropped the now-unnecessary
modImplementation 'maven.modrinth:levelz:1.4.11+1.20.1'Gradle dependency and the"levelz": "*"fabric.mod.jsondepends entry entirely — the code it used to compile against is now in the same source tree.
- Extract the Mod Menu screen. Same single-entrypoint-per-id constraint as the previous three merges. PartyAddon's standalone
ModMenuIntegration implements ModMenuApiclass was deleted, and WandererZ's combined chooser screen gained a fifth button that opensAutoConfig.getConfigScreen(PartyAddonConfig.class, this). - Merge the manifest.
fabric.mod.json: appended PartyAddon'smain/cliententrypoints, registeredpartyaddon.mixins.jsonalongside the existing four mixin configs. No newdependsentry was needed (LibZ was already a shared dependency from the WandererZ base). - Add Gradle dependencies. Clumps and Xaero's World Map carried over as optional
modCompileOnlysoft-compat, unrelated to the LevelZ merge, gated by their ownisModLoadedchecks exactly as upstream. - Validate the fragile
@Redirecttarget before building.LevelExperienceOrbEntityMixin's@Redirect(method = "lambda$onPlayerCollision$4", ...)targets a synthetic lambda method name, which only exists ifnet.wandererz.entity.LevelExperienceOrbEntity's compiled lambda numbering matches what PartyAddon was built against. Verified this withjavap -pon the compiledLevelExperienceOrbEntity.classbefore trusting the hardcoded string — confirmedlambda$onPlayerCollision$4(PlayerEntity, Integer, Integer)exists with the expected 3-parameter signature, since WandererZ's orb class is structurally unchanged from the LevelZ version PartyAddon targeted. - Validate.
gradlew compileJavathengradlew buildon JDK 17 — both succeeded, producingwandererz-2.2.0.jar. Verified the jar contains the expectednet/partyaddon/**classes (29) and the mergedfabric.mod.json. - Version bump.
mod_versionwent from2.1.1→2.2.0— a MINOR semver bump (additive functionality, no breaking changes).
Things deliberately not changed
distributeLevelZXPconfig field name, andGroupLeaderAccess.addLeaderLevelZExperience/addLevelZExperiencemethod names — previously-shipped/own-API, not LevelZ class references.LevelZServerPlayerEntityMixin's class name — internal implementation detail, not exposed to players, kept for minimal diff and to avoid touching the mixin-registration string matching inPartyAddonMixinPluginandpartyaddon.mixins.json.- Clumps/Xaero's World Map compat mixins (
GuiMapMixin,ControlsHandlerMixin, theEventInitClumps hook) — unrelated third-party integrations, left untouched. - Non-English PartyAddon lang file — copied as-is, aside from the mechanical "LevelZ" → "WandererZ" word swap in the one display-label string referencing the brand.
Risk register (resolved)
| Risk | Resolution |
|---|---|
| Mod Menu only showing one config per button slot | Added a fifth button to the existing combined chooser Screen |
net.levelz.* imports no longer resolving |
Repointed to the equivalent net.wandererz.* classes at their actual current paths |
@Redirect targeting a synthetic lambda method name by string, silently breaking at runtime if the index didn't match |
Verified the exact lambda signature via javap -p against the actual compiled class before trusting the hardcoded index |
isModLoaded("levelz") becoming a dead/always-false check |
Repointed to "wandererz", now a tautological always-true check (consistent with JobsAddon/RpgDifficulty/Tiered) |
| Previously-shipped config field getting renamed and silently resetting existing PartyAddon user configs | Left distributeLevelZXP unrenamed, following the JobsAddon precedent |
| Hidden package/mixin-target/resource collisions | Verified none exist via full file-tree review before copying — net.partyaddon is fully disjoint from all other merged packages |