Placeholders
AstralJobs registers one root namespace, jobs, with AstralCore (JobsPlaceholders, registered on enable via RootPlaceholderContainer#registerPlaceholder). Everything else — job_*, action_*, reward_*, booster_* — is a chain point reached by walking through jobs_*, or a namespace that other AstralJobs code registers directly into a PlaceholderContainer when it sends a message or resolves an item (for example, booster-activation messages in Messages register a BoosterEntity and its %booster_*% keys become available there). For the placeholder syntax itself (%a_b_c%, %a_{b_c}%, $e(...)) see Placeholders.
Several placeholders below require the placeholder context to be a Player (a menu/dialog opened for a player, or a message sent to one) — these are marked player-only. Most resolve to null outside that context; %reward_claimed% resolves to false, and the two booster-breakdown placeholders (boosterBonus, boosterMisc) resolve to 0 instead, because they are rendered inside menu lore where a null raises an InvalidWrapException and aborts the whole item compute.
jobs_* (root)
Placeholder | Type | Description |
|---|---|---|
| Job? | Looks up a loaded job by its |
| ItemProvider\<Job\> | Every loaded job. Use as a layout |
| double? | Player-only. The player's combined modifier for |
| double | The bonus percent contributed by active booster items alone, split by origin. Never |
| double | Player-only (yields |
| ItemProvider\<BoosterEntity\> | Every currently active global booster. No player context required. |
| BoosterEntity | The first active global booster of |
| ItemProvider\<BoosterEntity\>? | Player-only. Every booster currently active for the player. |
| BoosterEntity? | Player-only. The first active booster of |
Modifiers — jobs_modifier_<jobId>_<scope>_<sub>
Reads the player's active JobModifiers (PlayerJobModifiers, populated from booster activations and the permissions-boosters map in config.yml) and folds them into two running totals, both starting at 0.0: RELATIVE modifiers are summed into a bonusPercent as raw percentage values (matching PlayerJobModifiers#compute, which stacks them additively), ABSOLUTE modifiers are summed into a flat total. A modifier counts toward the query when:
its
scopeisGLOBAL(always counts, regardless of the queried scope), or itsscopematches<scope>exactly, andit has no
jobId(applies to every job) or itsjobIdequals<jobId>.
<scope> must be one of EXPERIENCE, MONEY, GLOBAL (case-insensitive) — anything else resolves to null. <sub> is optional and defaults to percent:
| Returns |
|---|---|
|
|
|
|
| The summed |
anything else |
|
Booster bonus — jobs_boosterBonus_<scope>_<source>
The bonus percent contributed by active booster items only, split by where the booster came from. Both tokens are mandatory:
<scope>is aJobModifierScope—EXPERIENCE,MONEY, orGLOBAL(case-insensitive).<source>ispersonalorglobal(lowercased before matching).
personal sums the player's active boosters (BoosterService#findActiveByPlayer) filtered to BoosterScope.INDIVIDUAL, so a global booster the player happens to own isn't counted twice; it is player-only. global sums BoosterService#globalActiveBoosters() and needs no player context.
For each booster the value is skipped unless the booster is active and affects the requested scope — a BOTH-type booster counts toward any scope, otherwise JobModifierScope.fromBoosterType(type) must equal <scope>. The per-booster bonus uses the same factor-or-bonus convention as multiplier (raw > 1.0 ? raw - 1.0 : raw, ×100) and the boosters sum additively.
The result is a percent (5.0 means +5%) and is never null: fewer than two remaining tokens, an unparsable <scope>, an unknown <source>, or (for personal) a non-player context all yield 0.
Booster misc — jobs_boosterMisc_<jobId>_<scope>
The residual bonus percent for <jobId>/<scope> — everything that is not an active personal or global booster item, i.e. in practice permissions-boosters entries plus anything another plugin added through JobsAPI.
Computed as total − personal − global, where total sums the value of every RELATIVE modifier on the player matching the same rules as jobs_modifier (ABSOLUTE modifiers are excluded), and personal/global are the same booster sums as boosterBonus. Because RELATIVE modifiers stack additively, personal + global + misc always equals the total shown by %jobs_modifier_<jobId>_<scope>%.
Player-only, but like boosterBonus it yields 0 rather than null outside a player context, on fewer than two remaining tokens, or on an unparsable <scope>.
job_*
A Job — reached via %jobs_job_<id>%, or from any placeholder container a job has been registered into directly. A bare %job_x% where x isn't one of the keys below (and isn't menu or player, which need a further sub-key) resolves to null; a bare %job% (no further token) resolves to the Job itself.
Placeholder | Type | Description |
|---|---|---|
| String | The job's |
| Component | The job's |
| ItemProvider\<JobActionPlaceholder\> | Every material/entity key in the job's |
| ItemProvider\<JobRewardPlaceholder\> | Every level in the job's |
| Component | The job's |
| ItemStack | The job's |
| ItemStack | The job's |
| int | Player-only, and needs a further sub-key. The player's level for this job ( |
| double | Player-only. The player's accumulated experience for this job, or |
action_*
A JobActionPlaceholder — one per material/entity key in a job's actions map (e.g. the sugar_cane entry under farmer's actions, which itself carries both a block-break and a block-place reward/experience pair).
Placeholder | Type | Description |
|---|---|---|
| TranslatableComponent | The material/entity's translatable name, computed once from the first action-type entry under this key ( |
| ItemStack | A representative icon |
| List\<Component\>? | Player-only. One rendered |
%action_computed% loops every action-type entry (e.g. block-break, block-place) defined for the key, looks up its localized label from action-type-displays in config.yml (skipping — with a warning logged — any entry with no matching label), and renders the action-display template once per entry with four extra placeholders scoped to that render:
Placeholder | Description |
|---|---|
| The entry's |
| The entry's |
| The action type's localized label from |
| The entry's |
reward_*
A JobRewardPlaceholder — one per level in a job's rewards map.
Placeholder | Type | Description |
|---|---|---|
| int | The reward's level key. |
| ComponentWrapperList | The reward's |
| Boolean | Whether the viewing player has already claimed this reward ( |
| Boolean? | Whether the player can claim it right now — not yet claimed and their current level ( |
booster_* (blueprint)
A BoosterBlueprint — one per file under boosters/ (see Boosters). Registered into a placeholder container wherever plugin code hands a blueprint off directly (for example, when activating a booster the blueprint is registered alongside the resulting BoosterEntity).
Placeholder | Type | Description |
|---|---|---|
| BoosterType |
|
| BoosterScope |
|
| Duration | The configured |
| String | The duration formatted for display, e.g. |
| double | The configured multiplier (e.g. |
| ItemStack | The blueprint's configured |
booster_* (active)
A BoosterEntity — an activated (or queued) booster instance, registered into a placeholder container by BoosterService whenever it sends an activation/expiry message (see the *-booster-activated/*-booster-expired keys in Messages) or resolved via %jobs_boosters_global_<TYPE>%/%jobs_boosters_player_<TYPE>% above. Shares the registered namespace booster with the blueprint above, but exposes a different set of keys:
Placeholder | Type | Description |
|---|---|---|
| UUID | The active booster instance's id (not the blueprint id). |
| MinecraftPlayerPlaceholder | The owning player — chain into |
| BoosterType |
|
| Component | The type's localized label — the |
| BoosterScope |
|
| long | The configured duration in milliseconds — a raw |
| long | Milliseconds remaining until expiry, clamped to |
| long | Milliseconds until a queued booster goes live ( |
| double | The multiplier this instance was activated with. |
| long | Epoch milliseconds when the booster expires. |
| long | Epoch milliseconds when the booster starts counting down (in the future for a queued global booster stacked behind another). |