Astral Realms Documentation Help

Overview

AstralScrolls turns "scrolls" — single-stack ItemStacks tagged with a hidden goal — into a progress-to-reward item type. A player receives a scroll of a given rarity, carries out whatever in-game goal the scroll rolled (break N blocks, kill N mobs, travel N blocks, …), and once the goal is met, right-clicking the completed scroll consumes it and grants a weighted-random reward from that rarity's reward pool.

What it does

  • A scroll is one ScrollBlueprint + one RarityBlueprint. When a scroll ItemStack is built, ScrollService#build picks a random ScrollBlueprint (weighted by that blueprint's chance for the target rarity), rolls a random requirement amount between that blueprint/rarity pair's min/max, and stores the result — id, rarity, blueprint, target, current progress — directly on the item's PersistentDataContainer via a custom PersistentDataType (ScrollDataType). The item itself is the only place scroll state lives; there is no separate player-progress database.

  • Progress is tracked by listening to the matching Bukkit event. Each ScrollBlueprint carries a ScrollGoal<E> — one of eight goal types (see Blueprints & Goals) — which is itself a per-event handler. GoalListener listens to all eight underlying Bukkit events at MONITOR priority and asks ScrollService#update to advance every scroll the player is currently holding whose blueprint's goal matches that event type.

  • A per-player cache avoids scanning every inventory slot on every event. ScrollService#cache memoizes, per player, which inventory slots hold an active (incomplete) scroll and which goal classes are in play, rebuilding it after 10 seconds or whenever CacheListener sees an inventory-changing event (quit, drop, pickup, inventory click/drag) that could have moved a scroll.

  • Completion re-tags the item and fires an event. When a goal update brings a scroll's value to (or past) its total, ScrollService#update re-styles the ItemStack with completed-item (from config.yml), adds a fake enchant glint, calls ScrollCompletedEvent, and — if completion-actions is configured — runs that action list.

  • Redeeming is a right-click. ItemListener intercepts PlayerInteractEvent for any held item that resolves to a completed scroll: it cancels the interaction and calls ScrollService#giveReward, which rolls one RarityBlueprint.RewardGroup (weighted by chance), runs its actions, and removes the scroll from the player's inventory.

  • Scrolls can't be placed as blocks. ItemListener cancels BlockPlaceEvent for any item stack that resolves to a scroll (completed or not).

Requirements

Dependency

Required

Notes

Paper 1.21+

Yes

api-version: '1.21'.

AstralCore

Yes

Declared in plugin.yml. Configuration/action framework, placeholders, the item-supplier registry, ACF command registration.

Configuration & commands

config.yml holds the scroll-item/completed-item display templates, the rarities map (display name, color, base ItemStackWrapper, and reward pool per rarity), and an optional completion-actions list run whenever any scroll finishes. Scroll definitions — the goal + per-rarity requirement chances/ranges — live one-or-more-per-file under blueprints/ (the plugin ships example.yml). See Configuration and Blueprints & Goals.

The only command is /scrolls, with give, rewards, and reload subcommands. There is no dedicated "buy a scroll" flow — scrolls are handed out via /scrolls give, the [give-item] action, or any other AstralCore call site that accepts an item-supplier key, using the scrolls:<rarity-id> namespace the plugin registers on enable. See Commands and Developer API.

See also

  • Blueprints & Goals — the blueprints/*.yml schema and all eight ScrollGoal types.

  • Placeholders — the %scroll_*% and %rarity_*% namespaces.

  • Messagesmessages.yml, including the goal-type-name labels used in item lore.

  • Developer APIScrollService, GoalService, ScrollCompletedEvent, and the scrolls:<id> item-supplier namespace.

Last modified: 25 July 2026