Blueprints & Goals
A blueprint is a scroll's goal plus how likely/how big that goal is per rarity. Blueprints live under blueprints/*.yml (see Configuration) and are deserialized by ScrollBlueprintTypeSerializer.
Schema
YAML key | Java field | Type | Description |
|---|---|---|---|
(map key, under |
| String | The blueprint's id — matched against by |
|
|
| The goal this blueprint tracks. |
|
|
| Which rarities this blueprint can be rolled for, keyed by rarity id (must match a key under |
Each requirements entry is a RequirementValues:
YAML key | Java field | Type | Description |
|---|---|---|---|
|
| double | Relative weight in a |
|
| int | Lower bound (inclusive) of the random goal target. |
|
| int | Upper bound (inclusive) of the random goal target. |
When ScrollService#build rolls a scroll for a rarity, the target (Scroll#total) is ThreadLocalRandom.nextInt(min, max + 1).
Goal types
Registered in GoalService's constructor. The type string under goal: is the documentation id, not the Java class name.
| Class | Underlying event | Config fields |
|---|---|---|---|
|
|
| |
|
|
| |
|
|
| |
|
|
| |
|
| (none) | |
|
| (none) | |
|
|
| |
|
|
|
Every goal advances scroll progress via GoalListener, which listens to all eight events at EventPriority.MONITOR with ignoreCancelled = true and calls ScrollService#update(player, GoalClass, event) — that call is a no-op unless the player's scroll cache currently has an incomplete scroll whose blueprint's goal is exactly that class.
kill
KillEntitiesGoal(List<EntityType> entities). On EntityDeathEvent, adds 1 progress if event.getEntityType() is in entities and the killer (getDamageSource().getCausingEntity()) is a Player.
break-block
BreakBlockGoal(List<Material> materials). On BlockBreakEvent, adds 1 progress per block broken whose material is in materials. Three extra rules:
Player-placed guard.
GoalListeneronly forwards aBlockBreakEventtoBreakBlockGoalifBlockService#wasPlacedByPlayerreturnsfalsefor the broken block — breaking a block a player placed never counts toward abreak-blockgoal.Growth check. For an
Ageableblock (crops) not fully grown (age < maximumAge), the break is ignored unless the material is one ofSWEET_BERRY_BUSH,CACTUS,SUGAR_CANE, orBAMBOO(the stackable-column materials).Column bonus. For those same stackable materials, breaking the bottom block of a column also credits 1 progress for every additional block of the same material stacked directly above it (so breaking the base of a 4-tall sugar cane column adds 4 progress in one break, not 1).
place-block
PlaceBlockGoal(List<Material> materials). On BlockPlaceEvent, adds 1 progress if event.getItemInHand().getType() is in materials.
craft
CraftGoal(List<Material> materials). On CraftItemEvent, adds 1 progress if the recipe's result material (event.getRecipe().getResult().getType()) is in materials.
enchant
EnchantGoal() — no config fields. On EnchantItemEvent, always adds 1 progress (any enchant counts).
travel
TravelGoal() — no config fields. On PlayerMoveEvent, adds (int) from.distance(to) progress — truncated block-distance moved since the last tracked position. GoalListener only forwards the event if hasChangedBlock() is true and at least 500ms have passed since the player's last travel update (per-player debounce, independent of any scroll state).
harvest
HarvestGoal(List<Material> materials). On PlayerHarvestBlockEvent, adds 1 progress if any of event.getItemsHarvested() has a type in materials.
fishing
FishingGoal(List<Material> fishes). On PlayerFishEvent, adds 1 progress if the event state is CAUGHT_FISH, the caught entity is an Item, and its ItemStack material is in fishes.
%scroll_context%/%scroll_type%
Every goal implements name() (a localized label pulled from messages.yml — see Messages) and context() (a Component describing the goal's targets, e.g. a comma-joined, translatable list of materials/entities). Both are exposed as scroll placeholders — %scroll_type% and %scroll_context% respectively — see Placeholders. enchant's context() returns null; travel's returns an empty component.