-
Notifications
You must be signed in to change notification settings - Fork 58
Pets
The Pets addon is an optional premium add-on for X-Prison that adds collectible Resource Pets. Each pet is a real item — no database, no per-player storage — that a player carries in their inventory and toggles active to receive a boost. Pets come in configurable rarities (Common → Pristine), each with its own boost band, and grow by being levelled, prestiged and fused, turning your economy into a long-term progression sink.
Because a pet is its item, everything about it (rarity, level, prestige, mined XP, active flag) lives in the item itself. Trade it, store it, drop it — the boost follows the item.
| Requirement | Notes |
|---|---|
| X-Prison |
2026.3.0.2 or newer |
| Java 17+ | Required |
| Paper / Spigot | 1.16 – latest (custom GUIs require MiniMessage) |
| Currencies module | Required — pets boost mining income and are upgraded with currency |
| Pickaxe Levels module | Optional — only needed for the Pickaxe Pet |
| PlaceholderAPI | Optional — only needed for the placeholders below |
Currencies: a currency pet boosts a currency by its internal name (
tokens,money,gems, …) and is upgraded with the currency set in itscost-currency. Those currencies must be registered in currencies.yml.
Folia is not supported. X-Prison core and this addon both schedule through helper's Bukkit-backed scheduler, so the addon is no more Folia-capable than the core it plugs into.
- Download
X-Prison-Pets-*.jarfrom your purchase platform. - Place the JAR inside
plugins/X-Prison/addons/. - Restart the server (do not use
/reload). - Default configs are created at
plugins/X-Prison/addons/Pets/—config.yml,pets.yml,eggs.yml,gui.yml,messages.yml. - Edit them to taste, then run
/petsadmin reloadto apply changes without restarting.
Upgrading: new config keys are added to your existing files automatically and your customised values are never overwritten. When a key has to move between releases, the addon migrates it for you and backs up every file it rewrites as
<name>.v<version>.bak.config-versionat the top ofconfig.ymlrecords how far your files have been brought forward — leave it alone.Upgrading from 1.0.x: the Pet Egg's display name moved out of
gui.yml(egg-item.name) into each egg'snamein the neweggs.yml. If you customised it, it is copied onto your default egg automatically.
pets.ymlis deliberately never auto-merged, because it holds your own pet definitions. New optional blocks such asxp:andmilestones:must be added by hand — pets without them simply keep the old behaviour.
-
Players obtain Pet Eggs (via
/petsadmin give-egg, crates, enchant rewards, etc.). Right-clicking an egg hatches it — an animated menu reveals a random pet at a random (weighted) rarity, then the pet drops into the inventory. Hatching can be turned off for an instant grant. -
Right-click a pet in hand to toggle it active, or shift-click it in the
/petsmenus. Active pets are marked with a subtle glint and count toward the active-pet limit (general.max-active-pets, raised per-player with thexprison.pets.active.<n>permission).Pets are carried, not worn. Most pets are player heads, which vanilla would otherwise let a player equip into the helmet slot; every route to doing so (clicking, dragging, number-key swapping, shift-clicking and dispensers) is blocked, and the message is configurable as
pet_cannot_be_worn. Shift-clicking a pet still moves it between hotbar and inventory normally. -
An active pet applies its boost. A currency pet multiplies that currency's income; the Pickaxe Pet multiplies Pickaxe XP. Which gains qualify is configurable — see Which gains pets boost.
-
Open
/petsto browse every pet type and its per-rarity boost table, and to open the Pet Upgrades, Pet Prestiges and Pet Fusion pickers. -
Upgrade a pet to raise its level from the band minimum toward the band maximum, paying its
cost-currencyper level (buy one, or bulk-buy as many as you can afford). Pets can also earn levels by mining, if you enable Pet XP. -
Prestige a maxed pet to reset its level and gain a permanent boost multiplier that stacks every prestige.
-
Fuse duplicate pets into a higher rarity — see Pet Fusion.
The live boost is:
levelValue = min + (max - min) * (level - 1) / (maxLevel - 1)
effectiveBoost = levelValue * (1 + prestige * per-prestige-percent)
Four pets ship by default. Add, edit or remove any of them in pets.yml.
| Pet | Boosts | Upgrade currency | Max level | Max prestige |
|---|---|---|---|---|
| Token Pet | Mining Tokens income | tokens | 40 | 10 |
| Money Pet | Mining Money income | money | 40 | 10 |
| Gem Pet | Mining Gems income | gems | 40 | 10 |
| Pickaxe Pet | All mining Pickaxe XP (multiplicative) | tokens | 100 | 15 |
Rarities are fully configurable under rarities: in config.yml. Order = display order and the fusion ladder; higher weight = more common; weight 0 = never rolled (admin-only).
| Rarity | Weight | Colour |
|---|---|---|
| Common | 600 | Gray |
| Rare | 250 | Aqua |
| Legendary | 100 | Gold |
| Mythical | 40 | Light Purple |
| Masterful | 9 | Red |
| Pristine | 1 | Dark Red |
Each pet defines a {min, max} boost band per rarity, so higher rarities are simply stronger versions of the same pet.
config-version: 2 # managed by the addon — do not edit
general:
max-active-pets: 1
maxed-text: "<gradient:#f7971e:#ffd200>Maxed</gradient>"
max-total-boost: -1 # ceiling on COMBINED boost per target (-1 = none)
diminishing-returns: 1.0 # falloff per extra active pet (1.0 = plain addition)
icon-cache-size: 512 # rendered menu icons kept in memory (0 = no caching)
permissions:
use: true # true (everyone) | op | false (nobody)
admin: op
boosts:
currency-causes: [MINING, MINING_OTHERS]
pickaxe-xp-sources: [MANUAL, AREA_ENCHANTS, AUTOMINER]
fusion:
enabled: true
carry-over: NONE # NONE | HIGHEST_LEVEL | AVERAGE_LEVEL
on-fail: CONSUME_INPUTS # CONSUME_INPUTS | REFUND_ONE | KEEP_INPUTS
default:
amount: 5
chance: 1.0
cost-currency: tokens
cost-formula: "50000 * pow(2, tier)"
overrides:
masterful: { amount: 8, chance: 0.35 }
rewards:
milestones-repeat-after-prestige: false
pet-egg:
hatching:
enabled: true # false = grant the pet instantly, no menu
animation-ticks: 60
close-delay-ticks: 40 # auto-close the menu after the reveal (0 = stay open)
frames: [WHITE_STAINED_GLASS_PANE, LIGHT_BLUE_STAINED_GLASS_PANE, YELLOW_STAINED_GLASS_PANE, LIME_STAINED_GLASS_PANE, PINK_STAINED_GLASS_PANE]
animation-sound: BLOCK_NOTE_BLOCK_HAT
reveal-sound: ENTITY_PLAYER_LEVELUP
reveal-particles: TOTEM_OF_UNDYING
effects:
upgrade-sound: ENTITY_EXPERIENCE_ORB_PICKUP
upgrade-particles: HAPPY_VILLAGER
prestige-sound: UI_TOAST_CHALLENGE_COMPLETE
prestige-particles: TOTEM_OF_UNDYING
sounds:
gui-open: { name: BLOCK_CHEST_OPEN, volume: 0.5, pitch: 1.2 }
gui-click: { name: UI_BUTTON_CLICK, volume: 0.5, pitch: 1.0 }
purchase-success: { name: ENTITY_EXPERIENCE_ORB_PICKUP, volume: 0.7, pitch: 1.4 }
purchase-fail: { name: ENTITY_VILLAGER_NO, volume: 0.7, pitch: 1.0 }
rarities:
common: { name: "Common", color: "<gray>", weight: 600 }
rare: { name: "Rare", color: "<aqua>", weight: 250 }
legendary: { name: "Legendary", color: "<gold>", weight: 100 }
mythical: { name: "Mythical", color: "<light_purple>", weight: 40 }
masterful: { name: "Masterful", color: "<red>", weight: 9 }
pristine: { name: "Pristine", color: "<dark_red>", weight: 1 }
commands:
pets: { name: pets, aliases: [pet] }
petsadmin: { name: petsadmin, aliases: [petadmin] }Boosts from several active pets are additive and, by default, unbounded. That matters as soon as you hand out xprison.pets.active.<n> — a player running several maxed high-rarity pets can multiply their income without limit. Two levers:
| Key | Effect |
|---|---|
general.max-total-boost |
Hard ceiling on the combined boost per target. 2.0 means pets can at most triple a gain. -1 disables the ceiling. |
general.diminishing-returns |
Falloff applied to each additional pet after the strongest. 1.0 = plain addition. 0.5 = 2nd pet counts half, 3rd a quarter, and so on. |
Pets are always ranked strongest-first before the falloff is applied, so a player's inventory order can never change their income.
The addon is built to stay out of the way on a busy server:
-
Menu icons are cached and shared. A pet's icon depends only on how it looks (type, rarity,
level, prestige, active), so players holding identical pets reuse a single render.
icon-cache-sizecaps how many are kept; the cache is cleared by/petsadmin reload. Set it to0to disable. -
Icons are built at startup, not the first time a player opens a menu. Startup logs
[Pets] Built N pet icon(s) in Xms— if that ever reports more than a few milliseconds it is flagged as a warning, because it means a pet icon is resolving its texture the slow way. - The hot paths bail out early. A currency gain for a currency no pet boosts, or pickaxe XP with no pickaxe pets configured, costs essentially nothing — no inventory is scanned to reach that conclusion.
- Active pets are cached per player and refreshed by events (inventory changes, death, toggling, upgrading, fusing) rather than on a timer, so mining does not repeatedly re-scan inventories.
Both lists were hard-coded before 1.1.0 and are now yours to set:
| Key | Default | Accepted values |
|---|---|---|
boosts.currency-causes |
[MINING, MINING_OTHERS] |
MINING, MINING_OTHERS, PAY, GIVE, REDEEM, LUCKY_BLOCK, REFUND, UNKNOWN
|
boosts.pickaxe-xp-sources |
[MANUAL, AREA_ENCHANTS, AUTOMINER] |
MANUAL, AREA_ENCHANTS, AUTOMINER, API
|
Unknown entries are logged and ignored. Leaving API out of the pickaxe list (the default) means Pickaxe XP granted directly by other addons is never boosted.
Each pet has one boost target and a per-rarity {min, max} band:
pets:
token_pet:
display-name: "<gradient:#f7971e:#ffd200>Token Pet</gradient>"
description: "increases the <yellow>Tokens</yellow><gray> you earn while mining"
boost-target: tokens # a currency name, or "pickaxe_xp"
boost-display: "Token"
material: PLAYER_HEAD
head-texture: "<base64 skin value>"
max-level: 40
max-prestige: 10
per-prestige-percent: 0.25 # +25% permanent boost per prestige
cost-currency: tokens
cost-formula: "5000 * pow(1.18, level)" # exp4j; variable: level = cost of NEXT level
weight: 100 # relative chance inside an egg; 0 = admin-give only
# Optional — see "Pet XP" below.
xp:
enabled: true
level-source: BOTH # PURCHASE | XP | BOTH
per-block: 1.0
rarity-multiplier: true
formula: "250 * pow(1.14, level)"
# Optional — see "Milestones & prestige rewards" below.
milestones:
25:
commands: ["tokens give %player% 25000"]
messages: ["<gold>Milestone! <gray>+25,000 Tokens at level <white>%threshold%<gray>."]
sound: UI_TOAST_CHALLENGE_COMPLETE
prestige-rewards:
1:
messages: ["<light_purple>First prestige on your <reset>%pet%<light_purple>!"]
rarities:
common: { min: 0.045, max: 0.19 }
# rare / legendary / mythical / masterful / pristine ...weight controls how likely a pet is to come out of an egg once a rarity has been rolled. All pets default to 100 (an even split); halve it to make a pet twice as rare as its siblings, or set 0 to keep it out of eggs entirely.
The gui.yml and messages.yml files are fully configurable too (menu titles, slots, materials, all lore, sounds and every player-facing string). All text is MiniMessage — gradients, hex and legacy & codes all work, and item text is rendered non-italic by default. Setting a message to "" silences it entirely.
You can define as many kinds of Pet Egg as you like. Each has its own icon, name, pet pool, rarity odds and hatch length. The first egg defined is the default — it is what /petsadmin give-egg <player> hands out, and what an egg created before 1.1.0 is treated as.
eggs:
basic: # the default egg
name: "<gradient:#f7971e:#ffd200><bold>%rarity%Pet Egg</bold></gradient>"
material: GHAST_SPAWN_EGG
glow: true
pet-pool: ["*"] # "*" (or omitted) = every pet in pets.yml
rarity-weights: {} # empty = inherit the global table
show-odds: true
animation-ticks: -1 # -1 = inherit pet-egg.hatching.animation-ticks
legendary_egg: # cannot roll Common or Rare at all
name: "<gradient:#c471ed:#f64f59><bold>%rarity%Legendary Egg</bold></gradient>"
material: DRAGON_EGG
pet-pool: ["*"]
rarity-weights:
common: 0
rare: 0
legendary: 600
mythical: 300
masterful: 90
pristine: 10
animation-ticks: 80
pickaxe_egg: # themed: only ever yields the Pickaxe Pet
name: "<gradient:#f85032:#e73827><bold>%rarity%Pickaxe Egg</bold></gradient>"
material: NETHERITE_PICKAXE
pet-pool: [pickaxe_pet]rarity-weights replaces a rarity's global weight rather than adding to it; rarities you do not mention keep their global weight. A weight of 0 means the egg can never roll that rarity, and it is omitted from the tooltip entirely.
With show-odds: true the tooltip lists each possible rarity with its real probability for that egg. Precision widens as outcomes get rarer, so a 1-in-1000 pet reads 0.10% rather than 0%.
By default pets only grow when a player spends currency, which means a pet makes no progress while its owner is actually playing. Add an xp: block to a pet and it earns experience per block mined and levels itself up.
| Key | Effect |
|---|---|
enabled |
Turns mined XP on for this pet. |
level-source |
PURCHASE (buy only), XP (mine only — the upgrade button is hidden), BOTH. |
per-block |
XP granted per block broken. |
rarity-multiplier |
Scale per-block by the pet's rarity: each step up the ladder earns 25% faster. |
formula |
exp4j expression, variable level — the XP needed for the next level. |
XP is stored in the item, so this keeps the addon's no-database design. It is banked in memory and written to the item only when a pet actually levels, on logout and on shutdown — so an area enchant breaking hundreds of blocks costs one item write, not hundreds. XP banked for a pet that is traded away before the write is discarded rather than applied to another pet. A pet at its level cap stops banking XP.
Duplicate pets are otherwise dead weight: once a player owns a pet of a given type, every further copy is worthless. Fusion turns that surplus into a chase and a second currency sink.
A fusion consumes N pets of the same type and rarity, charges a cost, and rolls a chance to produce one pet a step up the rarity ladder (the order rarities are declared in config.yml). Reachable from the Pet Fusion button in /pets.
| Key | Effect |
|---|---|
enabled |
Master switch. When off, the /pets button is not drawn at all. |
carry-over |
What the result inherits: NONE (level 1), HIGHEST_LEVEL, AVERAGE_LEVEL. |
on-fail |
CONSUME_INPUTS (all lost), REFUND_ONE (all but one lost), KEEP_INPUTS (nothing lost — the cost is still charged). |
default.amount |
How many duplicates one fusion consumes (minimum 2). |
default.chance |
Success probability, 0.0–1.0. |
default.cost-currency / cost-formula
|
exp4j expression, variable tier — the source rarity's ladder position, starting at 0. |
overrides.<rarity> |
Per-rarity tuning keyed by the rarity being consumed. Any field left out is inherited from default. |
The pets consumed are always the player's weakest copies (lowest prestige, then lowest level), so a failed fusion can never eat their best one. Rarities a pet has no band for are skipped rather than producing an unusable pet.
Groups already at the top of the ladder are still listed in the menu, marked as such and not clickable — a player holding only max-rarity duplicates sees why they cannot fuse instead of an empty menu.
Any pet can pay out rewards when it reaches a given level or prestige. Rewards use X-Prison's standard RewardSet shape (commands, messages, sound).
Placeholders available in both: %player%, %pet%, %pet_id%, %rarity%, %rarity_color%, %level%, %prestige%, %threshold%.
A bulk purchase that vaults several milestones at once fires each one exactly once. Because prestiging resets a pet to level 1, milestones are tracked per pet with a high-water mark so they cannot be farmed by prestiging repeatedly — set rewards.milestones-repeat-after-prestige: true if you want them repeatable.
| Command | Description | Permission |
|---|---|---|
/pets |
Open the pet catalog + Upgrade / Prestige / Fusion pickers | xprison.pets.use |
/petsadmin give <player> <type> <rarity> [amount] |
Give a pet | xprison.pets.admin |
/petsadmin give-egg <player> [egg] [rarity] [amount] |
Give Pet Egg(s) | xprison.pets.admin |
/petsadmin reload |
Reload the configs | xprison.pets.admin |
Aliases: /pet, /petadmin (configurable). Renaming a command in config.yml takes effect on /petsadmin reload — no restart needed.
give-egg's optional arguments are matched by what they are, not by position, so every pre-1.1.0 invocation still means what it always did:
/petsadmin give-egg Steve # default egg, random rarity, 1x
/petsadmin give-egg Steve 5 # default egg, random rarity, 5x
/petsadmin give-egg Steve pristine 3 # default egg, forced Pristine, 3x
/petsadmin give-egg Steve legendary_egg # Legendary Egg, its own odds, 1x
/petsadmin give-egg Steve legendary_egg pristine 3
| Permission | Effect | Default |
|---|---|---|
xprison.pets.use |
Open /pets, activate pets and open eggs |
everyone |
xprison.pets.admin |
Use /petsadmin
|
operators |
xprison.pets.active.<n> |
Raise a player's active-pet limit to <n>
|
not granted |
xprison.pets.active.* / xprison.pets.limit.bypass
|
Unlimited active pets | operators |
The addon registers these nodes with Bukkit on startup, so they show up in LuckPerms tab-completion and the web editor without you typing them out. xprison.pets.use is granted to everyone by default so pets work out of the box; an explicit grant or denial in your permission plugin always overrides the default.
If you would rather sell pet access as a rank perk, flip the default and grant it to the ranks that should have it:
permissions:
use: false # true (everyone) | op (operators only) | false (nobody)
admin: opxprison.pets.active.<n> is an open-ended family (.2, .3, …) so it cannot be pre-registered — grant the specific level you want per rank.
Requires PlaceholderAPI. Identifier xprisonpets. All active_* values describe the player's first boosting pet.
| Placeholder | Returns |
|---|---|
%xprisonpets_active_count% |
Pets flagged active, including any over the limit |
%xprisonpets_boosting_count% |
Pets actually granting a boost |
%xprisonpets_over_limit_count% |
Pets flagged active but beyond the limit |
%xprisonpets_active_limit% |
The player's active-pet limit (∞ if unlimited) |
%xprisonpets_active_name% |
First active pet's name |
%xprisonpets_active_target% |
What it boosts (e.g. Token) |
%xprisonpets_active_rarity% |
Its rarity |
%xprisonpets_active_level% |
Its level |
%xprisonpets_active_maxlevel% |
Its max level |
%xprisonpets_active_prestige% |
Its prestige |
%xprisonpets_active_boost% |
Its effective boost, e.g. 0.42
|
%xprisonpets_active_boost_percent% |
The same value as 42.0%
|
These read a snapshot maintained on the main thread, so they are safe for scoreboard, tab and chat plugins to resolve asynchronously.
Out of the box a pet's boost-target is either pickaxe_xp or any currency name (optionally currency:<name>).
A boost target is a strategy that decides for itself whether it applies to a given gain:
public interface BoostTarget {
String id();
String displayName();
boolean appliesTo(BoostContext context);
}BoostContext carries a kind (currency, pickaxe_xp, …) and a qualifier (the currency name, for instance). Register your implementation with the addon's BoostTargetRegistry before configs load; listeners never branch on concrete target types, so adding a target requires no changes to any existing class.
Candidate targets to build on this seam: a sell-multiplier on shop/AutoSell income, a flat gem/beacon/mob-coin drop bonus, an enchant proc-chance ("crit") boost, or a vanilla-XP boost.
Where is pet data stored? Nowhere — the pet is the item. Rarity, level, prestige, mined XP and the active flag are baked into the item, so there is no database and pets are fully tradeable.
Do currency pets boost /pay, sell-shop, or enchant currency rewards? Not by default — only mining income (MINING, MINING_OTHERS). You can widen or narrow that with boosts.currency-causes.
How many pets can a player have active? general.max-active-pets (default 1), raised per-player with xprison.pets.active.<n> or made unlimited with xprison.pets.active.*. Pets flagged active beyond the limit grant nothing and are marked as such in the menus.
Can I stop players stacking huge boosts? Yes — general.max-total-boost caps the combined boost per target, and general.diminishing-returns makes each extra pet count for less.
Can I turn off the hatching animation? Yes — set pet-egg.hatching.enabled: false and eggs grant their pet instantly.
Can I add my own pets, rarities or eggs? Yes — add entries under pets:, rarities: and eggs:. A pet may define bands for any subset of rarities; it can only roll at rarities it has a band for.
Do prestige boosts stack? Yes — each prestige adds a permanent +per-prestige-percent multiplier on top of the level boost, forever.
A player has more pets than fit in the menu. All menus paginate; use the arrows at the bottom.
Why didn't my pets start earning XP after upgrading? pets.yml is never auto-merged, since it holds your own pet definitions. Add an xp: block to each pet you want levelling by mining.
- Currencies
- Ranks
- Prestiges
- Rebirths
- Mines
- AutoSell
- AutoMiner
- Enchants
- Pickaxe Levels
- Pickaxe Skins
- Gangs
- Multipliers
- Blocks
- Bombs
- History
- Mining Stats
- Nicknames
- Battle Pass
- Quests
- Daily Rewards
- config.yml
- autominer.yml
- autosell.yml
- block-rewards.yml
- enchants.yml
- currencies.yml
- multipliers.yml
- ranks.yml
- prestiges.yml
- pickaxe-levels.yml
- pickaxe-skins.yml
- gangs.yml
- mines.yml
- bombs.yml
- blocks.yml
- history.yml
- mining-stats.yml
- rebirths.yml
- battlepass.yml
- quests.yml
- dailyrewards.yml
- efficiency.json
- fortune.json
- unbreaking.json
- haste.json
- speed.json
- fly.json
- nightvision.json
- jumpboost.json
- autosell.json
- tokenfinder.json
- gemfinder.json
- salary.json
- charity.json
- blessing.json
- gangvaluefinder.json
- prestigefinder.json
