Astral Realms Documentation Help

Developer API

AstralScrolls exposes its state through two services hung off the main plugin instance (plugin.scrolls(), plugin.goals()), one custom Bukkit event, and an item-supplier registration under the scrolls namespace. There is no static ScrollsAPI façade.

Maven coordinates

<dependency> <groupId>com.astralrealms</groupId> <artifactId>scrolls</artifactId> <version>1.0-SNAPSHOT</version> <scope>provided</scope> </dependency>

Repository: https://maven.astralrealms.fr/repository/maven-public/.

scrolls:<id> item supplier

On onEnable, AstralScrolls registers itself with AstralCore's item-supplier registry under the name scrolls:

AstralPaperAPI.registerItemStackSupplier("scrolls", new ScrollItemSupplier(this));

ScrollItemSupplier implements AstralCore's ItemStackSupplier contract, resolving <id> as a rarity id (not a blueprint id):

Method

Behavior

get(String id)

plugin.configuration().findById(id) (a RarityBlueprint) then plugin.scrolls().build(blueprint) — throws IllegalArgumentException if id doesn't match a configured rarity.

get(Player player, Key key, int amount)

Same lookup using key.value(), then sets the built stack's amount to amount.

completions()

Every configured rarity id, as Key.key("scrolls", id).

keyOf(ItemStack itemStack)

plugin.scrolls().fromItemStack(itemStack) mapped through Scroll::rarityRarityBlueprint::idKey.key("scrolls", id), or null if the stack isn't a scroll.

# anywhere an item-supplier key is accepted actions: - "[give-item] scrolls:legendary"

See Commands.

ScrollService

Accessed via AstralScrolls#scrolls().

import com.astralrealms.scrolls.AstralScrolls; import com.astralrealms.scrolls.service.ScrollService; ScrollService scrolls = AstralScrolls.getPlugin(AstralScrolls.class).scrolls();

Method

Returns

Behavior

build(RarityBlueprint rarity)

ItemStack

Picks a random ScrollBlueprint weighted by that blueprint's chance entry for rarity, then delegates to the two-arg overload. Throws IllegalArgumentException if no loaded blueprint has a requirements entry for the rarity.

build(ScrollBlueprint blueprint, RarityBlueprint rarity)

ItemStack

Rolls a target between blueprint's min/max for rarity, builds a fresh Scroll, renders config.yml's scroll-item template onto rarity's base ItemStackWrapper, tags the PDC, and forces maxStackSize to 1. Throws IllegalArgumentException if blueprint has no requirements entry for rarity.

update(Player player, Class<T> goalType, E event)

void

Advances every incomplete scroll of goalType the player is holding (per the scroll cache) by calling that goal's handle, re-rendering the item, and — on completion — firing ScrollCompletedEvent and running completion-actions. This is what every GoalListener handler calls; see Blueprints & Goals.

fromItemStack(ItemStack itemStack)

Optional<Scroll>

Reads the scroll off the stack's PDC via ScrollDataType, or Optional.empty() if the stack has no meta or no scroll tag.

isScroll(ItemStack itemStack)

boolean

true if the stack's PDC carries a scroll tag at all (completed or not). false for a null /meta-less/empty stack.

findById(String id)

Optional<ScrollBlueprint>

First loaded blueprint whose id matches, across every blueprints/*.yml file.

giveReward(Player player, Scroll scroll)

void

Draws one RarityBlueprint.RewardGroup from scroll.rarity().rewards() (weighted chance), runs its actions, then scans the player's inventory for the matching scroll (by uniqueId) and removes it. No-op if the reward pool is empty.

cache(Player player)

PlayerCache

The player's memoized scroll-slot map, rebuilt if older than 10 seconds.

invalidate(UUID playerId)

void

Drops the cached entry for a player, forcing a rebuild on next access. Called by CacheListener on quit/drop/pickup/inventory-click/inventory-drag.

ItemStack scroll = scrolls.build(configuration.findById("common").orElseThrow()); player.getInventory().addItem(scroll);

GoalService

Accessed via AstralScrolls#goals(). A simple string→class registry, seeded in its constructor with the eight built-in goal types (see Blueprints & Goals).

Method

Returns

Behavior

registerGoal(String type, Class<? extends ScrollGoal<?>> goalClass)

void

Registers (or overwrites) the ScrollGoal class used to deserialize a blueprint's goal.type: "<type>" value.

findByType(String type)

Optional<Class<? extends ScrollGoal<?>>>

Looked up by ScrollBlueprintTypeSerializer while parsing a blueprint's goal: node; a miss throws SerializationException ("Unknown goal type: …") during blueprint loading.

plugin.goals().registerGoal("custom-goal", CustomGoal.class);

ScrollCompletedEvent

Extends AstralCore's AbstractEvent (supports both sync and async firing). Fired by ScrollService#update the moment a scroll's value reaches its total, before completion-actions runs.

Field

Type

Description

player

Player

The player whose scroll completed.

itemStack

ItemStack

The scroll's ItemStack, already re-styled with completed-item and glinting.

scroll

Scroll

The completed Scroll (rarity, blueprint, value == total).

Async or sync depending on the completing thread (!Bukkit.isPrimaryThread()), since update can run from any of the eight goal-tracking listeners. Not cancellable.

@EventHandler public void onScrollCompleted(ScrollCompletedEvent event) { event.getPlayer().sendMessage("Scroll " + event.getScroll().rarity().id() + " ready to redeem!"); }

Scroll persistence

A Scroll is stored on its ItemStack's PersistentDataContainer via ScrollDataType (PersistentDataType<PersistentDataContainer, Scroll>), under the key astralscrolls:scroll. Five sub-keys back the five Scroll fields (astralscrolls:id, :blueprint, :rarity, :total, :value); reading back a stored scroll re-resolves blueprint/rarity against the currently loaded configuration (ScrollService#findById/MainConfiguration#findById) and throws IllegalArgumentException if either id no longer matches a loaded blueprint or rarity.

Last modified: 25 July 2026