Repository navigation
Developer PartyAddon Integration
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.
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
-
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).
-
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 | 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 |
Player Guide
- Overview
- Getting Started
- Levels & Skills
- Jobs
- RPG Difficulty
- Tiered
- Party
- Food Spoilage
- Configuration
- Compatibility
- FAQ
Developer Guide