Repository navigation
Developer API Usage
This page shows the actual access-interface APIs used to bridge net.wandererz and net.jobsaddon (and that third-party addons can also hook into, since both are implemented on vanilla entity classes via Mixin and are safe to cast against on any PlayerEntity/ServerPlayerEntity).
net.wandererz.access.PlayerSyncAccess is implemented on PlayerEntity and lets any code (including Jobs) grant WandererZ progression without depending on WandererZ's internal stats manager:
package net.wandererz.access;
public interface PlayerSyncAccess {
void syncStats(boolean syncDelay);
void addLevelExperience(int experience);
void levelUp(int levels, boolean deductXp, boolean ignoreMaxLevel);
}Usage from net.jobsaddon.jobs.JobsManager#addJobExperienceLevels — granting WandererZ XP proportional to a job level-up:
if (ConfigInit.CONFIG.levelZXPMultiplicator > 0)
((PlayerSyncAccess) playerEntity).addLevelExperience(ConfigInit.CONFIG.levelZXPMultiplicator * jobLevel);net.jobsaddon.access.JobsManagerAccess is implemented on PlayerEntity and exposes the per-player JobsManager (job levels, job XP, employed jobs list — persisted via NBT):
public interface JobsManagerAccess {
JobsManager getJobsManager();
}JobsManager jobsManager = ((JobsManagerAccess) player).getJobsManager();
int minerLevel = jobsManager.getJobLevel("miner");
jobsManager.setJobLevel("miner", minerLevel + 1);
// Grant job XP (handles level-ups, sounds, advancement triggers, and network sync internally)
jobsManager.addJobXP(player, "miner", 25);
boolean isMiner = jobsManager.isEmployedJob("miner");
boolean canSwitch = jobsManager.canEmployJob("farmer");
jobsManager.employJob("farmer");JobsManager recognizes the 8 job name strings: "brewer", "builder", "farmer", "fisher", "lumberjack", "miner", "smither", "warrior".
The job XP curve (used internally by getNextJobLevelExperience) is:
int experienceCost = (int) (ConfigInit.CONFIG.jobXPBaseCost
+ ConfigInit.CONFIG.jobXPCostMultiplicator * Math.pow(getJobLevel(string), ConfigInit.CONFIG.jobXPExponent));net.jobsaddon.access.PlayerAccess is implemented on PlayerEntity and tracks the last block broken / recipe crafted per player, so mixins can avoid granting repeat XP for spamming the same action (e.g. repeatedly breaking/placing the same block):
public interface PlayerAccess {
boolean setLastBlockId(BlockPos blockPos, boolean building, int id);
int getLastBlockId();
Identifier getLastRecipeId();
void setLastRecipeId(Identifier identifier);
boolean isQuickCrafted();
void setQuickCraftedRecipe(boolean quickCrafted);
}Example from the TreeChop compat hook in net.jobsaddon.init.EventInit:
TreeChopEvents.AFTER_CHOP.register((world, player, pos, state, data, felled) -> {
if (player != null && !world.isClient() && felled) {
if (((JobsManagerAccess) player).getJobsManager().isEmployedJob("lumberjack")
&& ((PlayerAccess) player).setLastBlockId(pos, false, 0)) {
int xpCount = JobLists.lumberjackBlockIdMap.getOrDefault(
Registries.BLOCK.getRawId(state.getBlock()), ConfigInit.CONFIG.lumberjackXP) * data.getNumChops();
if (xpCount > 0) {
JobsServerPacket.writeS2CJobXPPacket((ServerPlayerEntity) player, "lumberjack", xpCount);
}
}
}
});Both mods use Fabric's networking API with their own custom payload classes:
-
net.wandererz.network.PlayerStatsClientPacket/PlayerStatsServerPacket -
net.jobsaddon.network.JobsClientPacket/JobsServerPacket
Example — pushing a job-sync packet to the client after a server-side change (used throughout JobsManager, PlayerManagerMixin, CommandInit):
JobsServerPacket.writeS2CJobPacket(jobsManager, serverPlayerEntity);Both packet namespaces are self-contained (jobsaddon:* / wandererz:* channel identifiers) and do not collide.
Both mods register custom advancement criteria so datapacks/advancements can react to level-ups:
-
net.wandererz.criteria.WandererZCriterion/SkillCriterion(+ their*Predicates) -
net.jobsaddon.criteria.JobUpCriterion/JobPredicate
JobUpCriterion is triggered from JobsManager#addJobXP on every job level-up:
CriteriaInit.JOB_UP.trigger((ServerPlayerEntity) playerEntity, string, getJobLevel(string));net.jobsaddon.mixin.player.PlayerManagerMixin#respawnPlayerMixin shows the canonical pattern for migrating per-player job state across the respawn entity swap:
JobsManager jobsManager = ((JobsManagerAccess) player).getJobsManager();
JobsManager newJobsManager = ((JobsManagerAccess) serverPlayerEntity).getJobsManager();
newJobsManager.setJobLevel("miner", jobsManager.getJobLevel("miner"));
newJobsManager.setJobXP("miner", keepInventory ? jobsManager.getJobXP("miner") : 0);net.rpgdifficulty.mixin.compat.ChangeAttributeMixin is the reverse direction of the bridge: a mixin in the RpgDifficulty package reading state from WandererZ's own net.wandererz.access.PlayerStatsManagerAccess, scaling a mob's health/damage/protection factor by the average overall level of players within playerRadius:
double level = ((PlayerStatsManagerAccess) playerEntity).getPlayerStatsManager().getOverallLevel();This mixin is runtime-gated by RpgDifficultyMixinPlugin on FabricLoader.isModLoaded("wandererz"), which is always true in the merged jar — see RpgDifficulty Integration for why that's intended.
See Architecture for the full package/mixin map these APIs live in.
Player Guide
- Overview
- Getting Started
- Levels & Skills
- Jobs
- RPG Difficulty
- Tiered
- Party
- Food Spoilage
- Configuration
- Compatibility
- FAQ
Developer Guide