Skip to content
Jan Kluka edited this page Jul 21, 2026 · 5 revisions

Pets Addon

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.


Requirements

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 its cost-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.


Installation

  1. Download X-Prison-Pets-*.jar from your purchase platform.
  2. Place the JAR inside plugins/X-Prison/addons/.
  3. Restart the server (do not use /reload).
  4. Default configs are created at plugins/X-Prison/addons/Pets/config.yml, pets.yml, eggs.yml, gui.yml, messages.yml.
  5. Edit them to taste, then run /petsadmin reload to 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-version at the top of config.yml records 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's name in the new eggs.yml. If you customised it, it is copied onto your default egg automatically.

pets.yml is deliberately never auto-merged, because it holds your own pet definitions. New optional blocks such as xp: and milestones: must be added by hand — pets without them simply keep the old behaviour.


How It Works

  1. 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.
  2. Right-click a pet in hand to toggle it active, or shift-click it in the /pets menus. Active pets are marked with a subtle glint and count toward the active-pet limit (general.max-active-pets, raised per-player with the xprison.pets.active.<n> permission).
  3. 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.
  4. Open /pets to browse every pet type and its per-rarity boost table, and to open the Pet Upgrades, Pet Prestiges and Pet Fusion pickers.
  5. Upgrade a pet to raise its level from the band minimum toward the band maximum, paying its cost-currency per level (buy one, or bulk-buy as many as you can afford). Pets can also earn levels by mining, if you enable Pet XP.
  6. Prestige a maxed pet to reset its level and gain a permanent boost multiplier that stacks every prestige.
  7. 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)

Pets

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

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.


Configuration (config.yml)

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] }

Capping stacked boosts

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.

Performance

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-size caps how many are kept; the cache is cleared by /petsadmin reload. Set it to 0 to 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.

Which gains pets boost

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.


Pet definitions (pets.yml)

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.


Egg tiers (eggs.yml)

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%.


Pet XP (levelling by mining)

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.


Pet Fusion

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.01.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.


Milestones & prestige rewards

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.


Commands & Permissions

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: op

xprison.pets.active.<n> is an open-ended family (.2, .3, …) so it cannot be pre-registered — grant the specific level you want per rank.


Placeholders

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.


Extending Boost Targets

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.


FAQ

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.

XPrison Logo

General

Modules

Default Configs

Enchant Configs — Passive

Enchant Configs — Currency Rewards

Enchant Configs — Key & Item Rewards

Enchant Configs — Area of Effect

Enchant Configs — Multipliers

Enchant Configs — Templates

Enchant Configs — Addons

Addons

Support

For Developers

Others

Clone this wiki locally