Astral Realms Documentation Help

Overview

AstralPets is the collectible pet system for the AstralRealms network. Players acquire pets as items, consume the item to add the pet to their collection, feed it food to level it up, and equip (activate) up to a configurable number of pets at once to receive passive bonuses — stats, periodic money, potion effects, storage, no-fall, and modifiers to AstralShop / AstralJobs / AstralRotatingShop. One equipped pet can also be spawned: rendered in the world, following the player, and (for some blueprints) rideable.

A spawned pet is an AstralMobs mob. PetEntity#spawn looks up the pet's mob-blueprint (entity.mob-blueprint, defaulting to pet-<blueprint id>) and calls MobsAPI.spawnOwnedMob(...) bound to the owner, so AstralMobs drives everything in the world: the rendered type, the follow-owner and idle-animation goals, move control and pathing. AstralPets keeps only the pet-domain concerns on top of it — a two-line packet nametag mounted on the mob, owner/pet bookkeeping, riding and equipment helpers, and the despawn event.

The pet is grafted onto the mob's placeholder tree as part of the spawn, so the mob blueprint's goals, skills, requirement-gated gear and spawn actions can read %mob_pet_name%, %mob_pet_level%, %mob_pet_blueprint_id% and so on. The Pet is held by reference, so levelling up or renaming is picked up without re-attaching. A pet naming an unknown mob blueprint logs an error and does not spawn.

PetEntity still extends the plugin's PacketEntity, but the packet entity itself is dormant: spawning broadcasts no packet-entity spawns, and the identity accessors delegate to the live AstralMobs entity. The old BaseEntityPacketListener is gone — AstralMobs' own packet listener does the type spoofing, so nothing needs to rewrite or cancel the real mob's packets any more.

Attributes are layered: the mob blueprint's, then the pet blueprint's entity.attributes, then the skin's — the skin is applied last, so its minecraft:scale or movement_speed wins.

Pets, blueprints and player data

Concept

Type

Notes

Pet

Pet

An owned instance: a random UUID, a renamable Component name, its PetBlueprint, experience/level, a PetInventory (storage), the ids of the permanent skins it wears (a list — skins stack, and appending is the only operation), and timestamps (equippedSince, lastMoneyGainTime) used for the money effect.

PetBlueprint

PetBlueprint (@ConfigSerializable)

The template: id, defaultName, display item, an EntityBlueprint (entity type, mob-blueprint, name tag, baby, rideable, attribute overrides), a PetRarity, its effects, maxLevel, and the skins it accepts. Loaded from blueprints/*.yml.

PetRarity

PetRarity

id, display, color, and a levelExpression — a Crunch-compiled math expression over level that yields the XP required to reach that level.

PetSkin

PetSkin

A permanent look loaded from skins/*.yml — a rendered entity type, baby form, size, gear, potion effects or raw metadata, handed to AstralMobs as spawn overrides. See Pet Skins.

PetPreset

PetPreset

A named snapshot of a player's active pets (uniqueId, name, petIds), re-applied in one click. See Pet Presets.

PetPlayerData

PetPlayerData

Per-player, synced via AstralSync: the full pets list the player owns, the activePetsIds (equipped pets, up to the max-active-pets cap), a single selectedPetId — the pet currently spawned in the world — and the player's presets.

A pet is added to PetPlayerData by right-clicking with its item (PetListener#onConsume), which consumes the item and calls PetPlayerData#addPet. The reverse — [pickup-pet] — rebuilds the item stack via PetService#buildItemStack and removes the pet from the player's data.

Leveling

Pets gain experience only by being fed: right-clicking a spawned pet with a registered food item fires PetInteractEvent, and EntityListener looks the item up against foodBlueprints() and calls PetService#gainExperience(player, pet, entity, foodBlueprint.experience() * amount).

  • The XP required for the pet's next level is Pet#experienceForLevel(level), evaluated from its rarity's levelExpression (e.g. the shipped common rarity is 32+((level-1)^2/4)).

  • gainExperience loops applying level-ups (firing PetLevelUpEvent each time) while accumulated XP covers the next level's requirement, up to the blueprint's maxLevel; at max level further food is rejected with PET_MAX_LEVEL and XP is not accumulated.

  • Every level-up recalculates the pet's storage size from its storage effect and re-applies all of the pet's effects (Pet#removeEffect + Pet#applyEffect) so level-scaled values immediately update.

  • A short-lived floating text display shows XP gained above the player's head after every feed.

Passive effects

Effects live on the blueprint as a list of WrappedPetEffect (a label, a free-form unit, a Map<Integer, Double> of cumulative values per level, a maxValue/maxLevel/unlockLevel, and the underlying PetEffect). How an effect reads is no longer part of the blueprint: a PetEffectView binds an effect to the pet's level and transformers turn that into lines. Every PetEffect implementation is level-scaling: value(level) sums every entry at or below the pet's current level. Effects are (re)applied to the owner on equip (PetEquipEvent), on player-data load, and after every level-up, and removed on unequip (PetUnequipEvent), quitting, or being fed past max level; unequipping one pet re-applies the remaining active pets afterwards so overlapping effect types on other equipped pets aren't lost.

Registered id

Class

Target system

Behavior

stats

StatPetEffect

AstralStats

Adds a StatModifier (additive or percentage) to a given stat key while equipped.

money

MoneyPetEffect

Core economy

Deposits money on a per-effect interval, paid out by an async task that runs every 30s and only pays once the pet has been equipped (and last paid) longer than the interval.

potion

PotionPetEffect

Bukkit

Grants an infinite PotionEffect at an amplifier equal to the effect's value; applied synchronously.

storage

StoragePetEffect

—

Sizes the pet's own storage inventory, openable via [open-pet-container].

rideable

RideablePetEffect

—

Unlocks riding once its cumulative value reaches 1 and the blueprint's entity.rideable is true.

no-fall

NoFallPetEffect

—

Cancels fall damage for the owner while any active pet has a positive value at its level.

shop-modifier

ShopModifierPetEffect

AstralShop

Adds an item- or category-scoped ShopModifier via ShopAPI.

jobs-modifier

JobModifierPetEffect

AstralJobs

Adds a JobModifier (scoped to money or experience, optionally to one job) via JobsAPI.

rotating-shop-modifier

RotatingShopModifierPetEffect

AstralRotatingShop

Adds a percentage modifier via RotatingShopAPI.

See Pet Effects for the full per-effect configuration shape.

Active vs. equipped pets

  • Active (equipped) pets contribute their passive effects regardless of whether one is currently spawned. [equip-pet] enforces max-active-pets (config.yml, default 1, overridable per permission — the shipped default grants group.roturier a cap of 2) and refuses to equip two pets that share the same blueprint (CANNOT_EQUIP_IDENTICAL_PET).

  • Selected/spawned is a single pet — PetPlayerData#selectedPetId — that is actually rendered in the world. [spawn-pet] despawns any pet already spawned for that player first (EntityService#spawn calls findByPlayer(player).forEach(PetEntity::remove)), so only one pet can follow the player at a time even if several are active.

  • Spawning is gated by the WorldGuard integration: if the pets flag denies the location, [spawn-pet] aborts with PET_SPAWN_DENIED_HERE.

  • [ride-pet] mounts the owner on the currently spawned pet if its blueprint is rideable and its rideable effect value at the current level is at least 1.

  • /pets (aliases pet, familiers, familier) opens the pets-main menu by default; give/food/reset/ reload are admin subcommands under the same base command. See Commands.

  • /pokedex (aliases animalerie, bestiaire) opens the pokedex menu, populated from a max-level Pet instance cached per loaded blueprint (BlueprintService#cachedPets) — a bestiary of every blueprint regardless of ownership.

  • Renaming runs through the rename dialog in dialogs/, enforcing max-pet-name-length before invoking [rename-pet]. config.yml's old rename-dialog block is gone.

  • Presets are created and deleted through the preset-create/preset-delete dialogs and applied from the presets layout of the main menu.

See Pet Blueprints for authoring blueprints, Pet Skins for looks, Pet Presets for saved loadouts, and Pet Food for food items, the feeding flow, and the food item supplier.

WorldGuard integration

If WorldGuard is present, WorldGuardHook registers a custom StateFlag named pets (default state ALLOW) during onLoad, and registers a SessionManager handler (PetsWGSessionHandler) during onEnable. WorldGuardHook.isPetsAllowed(player, location) returns false only when the flag resolves to DENY for that location — [spawn-pet] is the only caller, so the flag blocks spawning a pet in a region, not owning or equipping one. WorldGuard absent (or the flag failing to register) always allows spawning.

Requirements

Dependency

Required

Notes

Paper 1.21+

Yes

api-version: '1.21'; built against Java 25.

AstralCore

Yes

AstralPaperPlugin base, actions, placeholders, menus, dialogs, transformers, Configurate-based config loading.

AstralMobs

Yes

Spawns and drives every pet — see the engine description above. A pet's mob-blueprint is an AstralMobs blueprint.

packetevents

Yes

The nametag display and the PetInteractListener/PetInventoryListener client-packet handling.

AstralStats

Yes

Backs the stats pet effect.

AstralShop

Optional (softdepend)

Backs the shop-modifier pet effect.

AstralJobs

Optional (softdepend)

Backs the jobs-modifier pet effect.

AstralRotatingShop

Optional (softdepend)

Backs the rotating-shop-modifier pet effect.

AstralSync

Functional

Not listed in plugin.yml, but PetPlayerData is persisted and synced across servers through SyncAPI and a registered PetSnapshotAdapter.

WorldGuard

Optional (softdepend)

Registers the pets region flag; see above.

WorldEdit

Optional (softdepend)

Used by WorldGuard's location adapter.

The three shop/jobs effects are provided by hooks: their effect classes are only registered once the matching plugin is present, and a blueprint naming one on a server without it has that effect skipped with a warning rather than failing to load.

Architecture at a glance

plugins/AstralPets/ ├── config.yml ← menu title, max-active-pets, max-pet-name-length, maximum-presets ├── rarities.yml ← rarity tiers + XP curve (level-expression) + colours per rarity ├── messages.yml ├── blueprints/*.yml ← pet definitions: item, entity, rarity, effects, max-level, skins ├── skins/*.yml ← permanent looks a pet may take on ├── food/*.yml ← food items and their XP value ├── menus/*.yml ← pets-main, pet, pokedex ├── dialogs/*.yml ← rename, preset-create, preset-delete └── transformers/*.yml ← the effect/level display lines the item lore calls

Getter

Class

Responsibility

blueprints()

BlueprintService

Loads pet blueprints from the blueprints/ folder, caches a max-level Pet per blueprint for the pokedex.

skins()

SkinService

Loads skins, builds and recognises skin items, applies a skin, and turns an applied skin into AstralMobs spawn overrides.

foodBlueprints()

FoodBlueprintService

Loads food items and their XP values.

pets()

PetService

XP/level-up logic, building pet ItemStacks, PDC (de)serialization.

entities()

EntityService

Packet-entity lifecycle: spawn/despawn, viewer & world tracking, riding, spawn-location resolution.

menus()

MenuService

pets-main, pet-menu, pokedex menus.

dialogs()

DialogContainer

The rename, preset-create and preset-delete dialogs, loaded from dialogs/.

transformers()

TransformerContainer

The plugin-scoped transformers loaded from transformers/.

Player-triggered behavior is exposed as AstralCore actions rather than direct API calls:

Registered name

Class

Purpose

equip-pet

EquipPetAction

Marks a pet active, subject to max-active-pets and the no-duplicate-blueprint rule.

unequip-pet

UnequipPetAction

Marks a pet inactive and removes its effects.

spawn-pet

SpawnPetAction

Spawns the pet through AstralMobs (WorldGuard-gated) and sets it as selected.

despawn-pet

DespawnPetAction

Removes the spawned entity and clears the selected pet.

pickup-pet

PickupPetAction

Converts a pet back into an item stack in the player's inventory/mailbox and removes it from their data.

open-pet-container

OpenPetContainerAction

Opens the pet's storage inventory (no-op if its storage size is 0).

ride-pet

RidePetAction

Mounts the owner on the currently spawned pet if it's rideable at its level.

rename-pet

RenamePetAction

Renames a pet, enforcing max-pet-name-length.

create-preset

CreatePresetAction

Saves the active pets as a named preset.

apply-preset

ApplyPresetAction

Swaps the active pets for a preset's.

delete-preset

DeletePresetAction

Deletes a preset.

For configuration keys and defaults see Configuration; for the full command surface see Commands; for placeholders see Placeholders; for static/programmatic APIs see Developer API.

Last modified: 25 September 2026