Shop Configuration
Every .yml/.yaml file under <plugin-data-folder>/shops/ is one shop. On enable, and again on /shop reload, PaperShopService#load() calls configurationManager().loadFolder(dataPath.resolve("shops"), ShopConfiguration.class), which walks the folder, deserializes each file into one ShopConfiguration, and indexes it by its own id field (not the filename) in an in-memory map. AstralShop ships one example, shops/wood.yml.
Example
Top-level fields
Field | Type | Description |
|---|---|---|
| String | The shop's identifier. Used as the map key shops are stored under and resolved by (e.g. |
| ComponentWrapper | The shop menu's title. A MiniMessage/legacy-formatted string, placeholder-aware like any other |
|
| The inventory slot indices this shop's items occupy. Exposed to the shop's menu blueprint as |
|
| The shop's items, keyed by item id. See items entries. |
ShopConfiguration also implements ComplexPlaceholder under the shop namespace, chaining id, title, slots, and items (the latter as an item-provider list). See Placeholders.
items entries
Each key under items: becomes one ShopItem; the YAML map key itself (oak_wood above) is captured as the item's id (ShopItemTypeSerializer reads node.key()). Fields, with their ShopItemTypeSerializer defaults:
Field | Type | Default | Description |
|---|---|---|---|
| double |
| Price to buy one unit, before per-player modifiers. Charged as |
| double |
| Payout for selling one unit, before modifiers. Paid as |
| ItemStack | — (required) | The item's appearance, and the exact |
| boolean |
| If |
| boolean |
| If |
| boolean |
| If |
| AstralCore action list | none | Run on a successful buy, in place of the item grant when |
| AstralCore action list | none | Run on a successful sell, in addition to the normal payout and item removal. |
display
display is a standard Bukkit ItemStack — the shipped example only sets material, name, and lore:
Field | Description |
|---|---|
| A |
| Legacy |
| List of lore lines. |
AstralCore's ItemStack deserializer also accepts amount, enchantments (Map<String, int>), unbreakable, max-stack-size, enchantment-glint-override, custom-model-data, and item-flags — none of which wood.yml uses. This item stack is resolved once at load time; it is not placeholder-aware the way a menu's item-stack block is (see Menu Items).
buy-actions and sell-actions
Both are AstralCore action lists — "[action-id] args" strings run through PaperActionFactory, exactly like any other action list in the ecosystem. See Actions for the full catalogue of action ids (e.g. [console], [message], [give-item]).
Buy: if
give-itemistrue,buy-actionsis never run — the configured item is granted directly instead. Ifgive-itemisfalse, the item is not granted andbuy-actionsruns in its place.Sell:
sell-actionsalways runs after a successful sale (payment deposited, items removed from the seller's inventory) — it isn't a substitute for anything and can be omitted entirely.
Category (shop id on items)
ShopItemTypeSerializer reads the enclosing shop's id back (node.parent().parent().node("id")) and stores it on every ShopItem as shopId. ModifierService uses this as the "category" a ShopCategoryModifier targets, letting a per-player price modifier apply to every item in a shop rather than one specific item. See Per-player price modifiers.
Menu rendering
/shop open <player> <shop> (and the [buy-shop-item]/[sell-shop-item] action flows) render a shop through MenuService#openShopMenu, which opens AstralCore's MenuContainer menu id shop (container.computeAndOpen(player, "shop", Map.of("shop", configuration))) — the clicked-or-opened ShopConfiguration is handed to the menu blueprint as its shop parameter, resolvable via %shop_*%/%item_*% placeholders.
AstralShop's own menus/ folder ships empty — it does not include a menus/shop.yml blueprint. A menu blueprint with id shop must be authored under the server's menus/ folder (Menu YAML format, see Menu Items) for /shop open to render anything; without one, opening a shop fails with IllegalArgumentException: Menu blueprint with id 'shop' not found.
Reloading
/shop reload (permission shop.command.reload) calls AstralShop#loadConfiguration(), which re-runs, in order:
shops.load()— reloads every file undershops/.menus.load()— reloads every menu blueprint undermenus/.loadEnum("messages.yml", ShopMessages.class)— reloadsmessages.yml.
See Commands for the full /shop command reference.
No config.yml
AstralShop has no config.yml — the shop files under shops/ and messages.yml are the only shipped configuration.