Astral Realms Documentation Help

Custom Requirements

You can register new requirement types that become available in view-requirements and clicks-requirements blocks of any menu or dialog YAML.

Step 1 — Implement Requirement

import com.astralrealms.core.paper.model.requirement.Requirement; import org.bukkit.entity.Player; // The constructor receives the argument string (after placeholder substitution). public record HasMoneyRequirement(double amount) implements Requirement { @Override public boolean test(Player player, Object context) { return EconomyPlugin.getBalance(player) >= amount; } }

Constructor argument resolution

Exactly the same adapter system used for actions applies here. Register adapters for any custom constructor types via AstralPaperAPI.registerAdapter(...).

Step 2 — Register the Requirement

AstralPaperAPI.registerRequirement("has-money", HasMoneyRequirement.class);

Step 3 — Use in YAML

Inline (shorthand)

view-requirements: - "[has-money] 500.0"

Object form (with deny-actions)

clicks-requirements: LEFT: - type: has-money value: "500.0" deny-actions: - "[message] <red>You need $500 to buy this." - "[sound] minecraft:entity.villager.no"

Deny Actions

When using the object form, deny-actions is a list of actions executed on the player if this requirement returns false. This is the correct place to send feedback messages.

Placeholder Substitution in Requirements

The value string (or inline argument) has all %placeholder% tokens substituted before the constructor runs:

- type: has-money value: "%param.price%"

The HasMoneyRequirement receives the numeric value resolved from %param.price%.

Context Object

The context parameter in test(Player player, Object context) is the menu's MenuContext when the requirement is evaluated inside a menu. It implements Function<String, Object> so you can resolve placeholders from it:

@Override public boolean test(Player player, Object context) { if (context instanceof Function<?, ?> fn) { @SuppressWarnings("unchecked") Function<String, Object> resolver = (Function<String, Object>) fn; Object val = resolver.apply("param.price"); // ... } return false; }
23 April 2026