EverGrims WerksTHE CROSSPLAY WERKSHOP

EverGrims Werks

GrimsShop

Public release 0.4.2 · Admin guide · Paper 26.3

Server shops, nested categories, rotating stock and quick selling, with support for EGW custom items and the optional Cannabis Dispensary.

Most work happens in /shop admin, or by right-clicking an item, section tile or rotating shop in /shop. Touch admins (as GrimsClientChecker decides) get forms for everything, with an Edit button on shop pages. Everyone else, Java and console or PC Bedrock, gets chest screens and Paper pop-up dialogs for typing and confirmations; Geyser shows a dialog as its own window on Bedrock. If typing in a dialog doesn't register on console or PC (Geyser issue #6377), /gcc menu shop mobile switches that admin to forms. Nothing is typed into chat.

Every save is checked first. If a change would break the shop files, it is refused, the errors are listed and the files stay as they were. Each file keeps a .bak of its previous version.

The shop itself is two folders of small YAML files, sections/ and shops/; The two folders explains them. The editor still calls a section a category, so the Categories page, New sub-category here and /shop admin category all work on sections.

When an item shows no buttons

A Buy or Sell button is only ever drawn for a trade that would actually go through, so a player is never offered a click that is certain to be refused. An item stops offering a side when:

The item shows no…because
Buy buttonit has no buy price
Sell buttonit has no sell price
eitherit is a unique captured mob, which this shop cannot trade
eitherits currency has no working economy provider — install one, or price it in an item currency. /shop status lists each currency and says (unavailable)
Buy buttonits stock is finite and has less than one whole bundle left. `/shop admin restock <shop\catalog> [item] refills it (catalog` for items on section pages)
Buy buttonit sells a GrimsSuperSpawners spawner and that plugin is not running, or no longer recognises the item the shop captured. The console names the listing
Buy buttonit sells an item an EGW plugin makes (fishin:, chests: and the rest, see Items the EGW plugins make) and that plugin is not running. The console names the listing

Both Buy: and Sell: lines always show on the item, and a side the shop will not trade reads -0 rather than disappearing. It is never clickable, so the prices and the buttons always agree. Set menu.listing.no-price in messages.yml to change it (none, 0 or a dash all work); it deliberately skips the currency, so it reads the same whatever the item is priced in. In the editor an unpriced side still reads none, which is how you tell "I never priced this" from "this cannot trade right now"; the log also names the reason with a risk rank. An item whose sides both read -0 does not open its own screen at all. The Sell items quick-sell button is hidden when the shop buys nothing back that the player is allowed to reach.

What a player can afford, or has room for, is not part of this: those prices stay visible, with their buttons, so they can see what they are short of.

Every one of these reasons is also reported to the server log with a risk rank Ask Nixie can alert on — see NIXIE-ERRORS.md.

The two folders: sections/ and shops/

The shop is made of sections: each one is a tile on the main menu (or on another section's page) and the page that tile opens. The editor calls them categories. Every section is a pair of files with the same name:

  • plugins/GrimsShop/sections/<id>.yml holds the section's settings: its name, icon, currency and place in the shop.
  • plugins/GrimsShop/shops/<id>.yml holds its items, in the order they show.

The file name without .yml is the section's ID: sections/farming.yml and shops/farming.yml are the Farming section, and /shop farming opens it. An ID uses letters, numbers, - and _, up to 40. The two names must match exactly, upper and lower case too. Only files ending in .yml are read. The README.txt in each folder, the .yml.bak copies and a file renamed to .yml.disabled are ignored. Each folder's README.txt has an example and every key.

Menus are built from memory: these files are read at startup, on /shop reload or /shop validate and when a change is saved, never when a player opens /shop.

Section files

# sections/farming.yml
name: "&aFarming"                  # & colour codes or MiniMessage; default: the ID
description: "Seeds, crops and more"
icon: {material: WHEAT}            # written like an item: material, skull, item-data or custom
currency: coins                    # from currencies.yml; default: config.yml defaults.category-currency
order: 3                           # sorts it among the sections beside it, lower first
KeyWhat it does
enabledfalse switches the section off without deleting anything (see Taking a section out). The default is true. enable: (EconomyShopGUI's spelling) works too; enabled: wins when both are there
nameits display name, with & codes or MiniMessage. The default is the ID
descriptionthe tile's description
iconthe tile's item, written like an item in a stock file. The default is a chest
currencythe default currency of its items. The default is defaults.category-currency in config.yml
permissionneeded to see and open it, and everything under it
form-imageits Bedrock touch button picture: a textures/... path or an https:// link
parentanother section's ID. This section is then a tile on that section's page, not on the main menu (see Sub-sections)
ordera whole number that sorts it among its siblings: the sections on the main menu, or those under the same parent. Lower comes first. A section without one sorts after every section with one, and ties go by ID, ignoring case
slot, pageon a main-menu section, slot is its main-menu slot. On a sub-section, page and slot pin its tile on the parent's page (see Fixed positions)
hiddentrue puts it on no menu or page; only /shop <id> opens it
pool-onlytrue means it is never shown; only rotating shops draw from its items

Every key is optional. A section with no items of its own but with sub-sections is a group tile: it opens their page. A section with nothing to show has no tile. That means no priced item in it or in a shown sub-section. items: or listings: in a section file is not read, and a warning says so: items go in shops/<id>.yml.

Stock files

# shops/farming.yml
items:
  wheat:                           # the item's ID: unique across every file in shops/ (case matters)
    name: Wheat                    # optional; default: the item's own name
    item: {material: WHEAT}
    buy: 4                         # per bundle; empty or missing: not sold
    sell: 1                        # per bundle; empty or missing: not bought back
    bundle-size: 16                # 1-64; default: config.yml defaults.bundle-size
  golden_carrot:
    item: {material: GOLDEN_CARROT}
    buy: 12

An item takes these keys:

  • name and item.
  • icon (or menu-icon): what the menu shows instead of the item.
  • buy and sell.
  • currency: overrides the section's.
  • bundle-size.
  • stock: {mode: FINITE, amount: 64} for limited stock. Stock is unlimited by default.
  • match: see Matching.
  • form-image, page and slot.
  • Order and drafts. Items show in the order they are written. An item with no price at all is a hidden draft, marked for staff in the editor, until it gets one. That is how a pack can ship a whole unpriced catalogue for you to price in game.
  • Only items: is read. Anything else at the top of the file gets a warning, which also catches a file still in 0.3.0's format. The file an item is in decides its section: a category: line on an item is ignored, with a warning.
  • No stock file just means the section has no items of its own. That is normal for a group section.
  • A stock file without its sections/ file is not loaded. /shop validate warns that shops/<id>.yml has no sections/<id>.yml, so its N item(s) are not in the shop. Its items take part in no ID clash.

Taking a section out

  • Delete both files, sections/<id>.yml and shops/<id>.yml, then run /shop reload. Delete in the editor does the same, once the section has no items and no sub-sections, and it keeps a .bak copy of both files.
  • Or set enabled: false in sections/<id>.yml and run /shop reload. Nothing is deleted. The section, its items and every section under it are simply not loaded: not on any menu, not /shop <id>, not bought or sold, and not in rotating shops. /shop reload and /shop validate list the switched-off sections, and report nothing inside them, not even a stock file that is not valid YAML. A sub-section's own file is still reported when the shop can't read it safely (it is not valid YAML, writes a key twice, or its name is not a valid ID or clashes with another), because then the shop can't tell which section it is under. Set it back to true, or delete the line, to bring it back. The editor refuses to put a section under a switched-off one, or under one that is switched off through a section further up.
  • Delete only shops/<id>.yml to take out its items and keep the section's settings. A section with nothing to show has no tile. Adding an item to it in game makes the file again.
  • Delete only sections/<id>.yml to take out the section and keep its items in shops/, with the warning above. A new section with that ID, made in game or by hand, picks the items up again.

A section you take out stays out: GrimsShop only writes the defaults when neither folder exists.

The default sets

Three sets are built into the jar. The first start writes every-block, when there is no sections/ and no shops/ folder.

SetWhat it is
every-blockEvery creative item except operator-only blocks, in 30 sections with 1843 items: potions (all four kinds), max-level enchanted books, spawn eggs, spawners. 26.3 items only show on 26.3 servers.
survivalevery-block without spawners, spawn eggs, the dragon egg and creative-only blocks
liteabout 220 SMP essentials in 11 sections
  • Swap in a set: run /shop admin defaults <every-block|survival|lite>. It needs grimsshop.admin.preset, and /shop admin preset still works as its old name.
  • The set is written to a staging folder and checked with your currencies.yml, layouts.yml and rotating-shops.yml first. If it would not load, the shop is left as it was and the errors are listed.
  • Otherwise your current sections/ and shops/ move to backups/<date>_<time>-defaults-<set>/, the set takes their place, and the shop reloads. The reply gives the counts and the backup folder.
  • Every rotating shop an import added (it has an imported-from: line in rotating-shops.yml) is removed too, because the sections it sold from were in the folders being replaced. Your own rotating shops, such as the Quick Market, stay. When shops are removed, the old rotating-shops.yml goes into the backup and the reply says how many.
  • /shop admin defaults on its own lists the sets and what the shop holds now.
  • Currency: every section of every set uses coins, the money currency in the bundled currencies.yml. If your currencies.yml has no coins, a set still goes in, but every section is left out with unknown currency coins (the reply lists it). Add a currency called coins, or put the backup back.
  • Prices: buy prices come from vanilla recipes, anchored on hand-set raw prices (wheat seeds 2, iron ingot about 20, diamond 200). Every sell price is 25% of buy. Change any of them in game or in the YAML.
  • Item IDs are the item names (oak_log, potion_long_swiftness, enchanted_book_mending). They are the same in every set and in imports, so a rotating shop's pool keeps working after a swap. Pool IDs the shop doesn't have are skipped.
  • Not part of a set: rotating shops, currencies, layouts and messages. A swap leaves them alone, except for the imported rotating shops above.
  • Drop-ins go too. Drop-in pairs such as the Custom tile are part of sections/ and shops/, so they move to the backup with everything else. Unzip them again after the swap.

Starting again

Stop the server, delete both sections/ and shops/ (or move them somewhere), and start it again: the every-block set is written afresh. If either folder is there, nothing is written. That includes folders made by unzipping drop-ins, so unzip them only after this start.

Backups, and going back

/shop admin defaults and /shop admin import never delete anything. The sections/ and shops/ they replace move to plugins/GrimsShop/backups/<date>_<time>-<defaults or import>-<set or plugin>/, with _2 added for a second one in the same second. A swap that changed rotating-shops.yml (by removing imported rotating shops, or by adding an import's) leaves the old copy there too. Nothing else writes to backups/.

To go back to a backup by hand:

  1. Move the current sections/ and shops/ out of plugins/GrimsShop/, or delete them.
  2. Move the backup's sections/ and shops/ back into plugins/GrimsShop/, and its rotating-shops.yml too if it has one.
  3. Start the server, or run /shop reload if it is running.

Every in-game edit also keeps the file's previous version as <file>.bak next to it. To undo one edit, copy the .bak over the .yml (take .bak off its name) and run /shop reload.

When a file has a problem

A problem in a section or stock file never closes the shop. Only that file, section or item is left out, with an error naming the file, and the rest opens. /shop validate lists every error, then the warnings. /shop reload and the console list them too, and the console reports them as catalog-left-out (see NIXIE-ERRORS.md).

  • A section is left out, with its items and every section under it, when:
  • its file name is not a valid ID;
  • another file already has the name, in any case (the first in name order wins);
  • the file is not valid YAML, or writes a key twice;
  • its parent is unknown, itself, pool-only or left out, or loops back to it;
  • its currency is unknown.
  • An item is left out when:
  • its ID is not valid, it is not a map, or it is written twice in its file;
  • a stock file earlier in name order already has that ID (case matters, and the error names both files);
  • its price is not a number, or its currency is unknown;
  • its currency is an item currency and a price is not a whole number.

items: written twice, or not a map, leaves that whole file's items out. A file saved with a byte-order mark at its start (some Windows and panel editors add one) is checked the same way, so a key written twice is still caught.

  • Warnings leave nothing out. They cover:
  • a stock file without its section file;
  • extra keys in a stock file, items: in a section file, and category: on an item;
  • an order: that is not a whole number (it is ignored);
  • a section ID that is a /shop command word: sell, help, admin, editor, reload, validate or status. /shop <id> runs the command, so the section only opens from its tile;
  • a section and a rotating shop with the same ID (/shop <id> opens the section);
  • a pinned slot that is taken or a button;
  • items this server's Minecraft version doesn't have.
  • The shared files close the shop. currencies.yml, layouts.yml and rotating-shops.yml are shared by every section. An error there keeps the shop closed at startup: a file that is not valid YAML, a currency, rotating shop or layout written twice (with or without a byte-order mark), more rotating shops than rotating-shops.max, or an unknown layout. A /shop reload with one of these errors is refused, and the last good version keeps running. rotating-shops.yml may be missing or empty.
  • No sections at all is valid: /shop shows only the rotating shops, or tells players the shop has nothing for them when there are none either.

Editing in game saves to the files

  • Section settings save to sections/<id>.yml: name, description, currency, permission, parent, slot, page, hidden, pool-only, icon and Bedrock picture. Only the keys that changed are written. The section's editor page names both of its files.
  • A section's Position among its siblings is written as order: 1..n across those siblings. Only the files whose number changes are touched. A section file that is left out (see When a file has a problem) is never rewritten for this, when you create, move or reorder a section; fix it by hand.
  • A new section gets both files. Make one from Categories, then Create, or with /shop admin category create.
  • sections/<id>.yml gets its name, an empty description, its currency, a chest icon and an order: that puts it last among its siblings.
  • shops/<id>.yml gets items: {}. If that file is already there (one whose section file was deleted), it is kept and its items join the new section.
  • The ID is refused when a section file already has it (in any case), a rotating shop has it, or it is a /shop command word.
  • Names that differ only in case. The editor never makes a file whose name differs from one already in that folder only in upper or lower case, such as shops/Stone.yml next to shops/stone.yml. Windows and macOS treat those as one file, so the change is refused with a message instead of writing over the other file. Pick another ID, or rename that file.
  • Items save to shops/<section>.yml: prices, stock, names, icons, Bedrock pictures, moves and deletes.
  • An item added from your hand goes at the end of its section's stock file, which is made if the section has none.
  • Moving an item to another section (its Category setting) moves its YAML to the end of that section's stock file. It is refused when that file already holds a left-out item with the same ID (a clash); rename or delete that one first.
  • A new item ID is refused if any stock file already has it.
  • Deleting an item also takes it out of every rotating shop's pool.
  • An item's Position counts among the items shown in its section. Items hidden on this server, such as a newer Minecraft version's or a custom item still loading, keep their places.
  • Nothing you didn't change is touched. Saving a form unchanged moves nothing, and the comments in the file stay. Saving a section's or an item's settings, an icon or a Bedrock picture without changing anything writes nothing at all, and so does /shop admin item price with the price the item already has, so the file and its .bak stay as they were. A price or match: you don't change keeps the shape it is written in (buy: 40, match: EXACT), even when you change something else. Saving the settings of a rotating shop, a currency or a layout, or a rotating shop's pool, always rewrites its file, so its .bak then holds the version from just before that save. An item without name: keeps showing its own (the pack's) name: saving its settings does not write that name in. In the same way an item without bundle-size: keeps following defaults.bundle-size in config.yml, and a section without currency: keeps following defaults.category-currency, until you pick a different value in the editor.
  • Deleting a section needs it to have no items (including items hidden on this server) and no sub-sections. Both files go, and each is kept as a .bak copy.
  • Every change is checked first. Some changes are not saved: one that would break the files, or one that would leave out something that was not left out before (an item moved into a section whose item currency can't pay its price, say). The files stay byte for byte as they were, a file the change created is deleted again, and the errors are listed. Problems already in the files don't count, so the usual fixes still work while something else is left out.
  • Hand edits are never overwritten. Every change reads the files fresh, so edits you made by hand since the last reload are kept. A file that is not valid YAML is never written over, and neither is a section file that writes a key twice or a stock file that writes items: or an item twice (what is written twice is left out, and saving the file would keep only the last one): any change that would save it is refused, naming what is written twice. Fix it by hand first.

Importing another shop plugin

/shop admin import replaces the shop's sections/ and shops/ with another shop plugin's shop. It needs grimsshop.admin.preset. Your current folders are moved to backups/ first, so nothing is lost.

/shop admin import list                                             which plugins are supported, and which were found
/shop admin import economyshopgui dry-run                           read everything and show what would be imported; writes nothing
/shop admin import economyshopgui                                   replace sections/ and shops/ with plugins/EconomyShopGUI-Premium
/shop admin import economyshopgui from:old/EconomyShopGUI-Premium   read a folder copied from another server (a path from the server folder)
/shop admin import essentials                                       replace them with EssentialsX's worth.yml (plugins/Essentials)
  • Supported: EconomyShopGUI and EssentialsX worth.yml. Other shop plugins come later.
  • EconomyShopGUI free and Premium both work: the 6.x layout with subfolders, the flat sections/ and shops/ layout, and the old single-file layout.
  • Its folder is read from plugins/EconomyShopGUI-Premium or plugins/EconomyShopGUI. Its jar doesn't have to be installed, and is better out, since it also uses /shop.
  • What happens:
  • The source is read and written as section pairs into a staging folder, .staging-import/.
  • The pairs are checked with your currencies.yml and layouts.yml and the new rotating-shops.yml. If they would not load, nothing changes and the errors are listed. If nothing at all could be imported, nothing changes either.
  • Your current sections/ and shops/ move to backups/<date>_<time>-import-<plugin>/, and the import takes their place. When the import changes rotating-shops.yml, a copy of the old one goes into the backup too.
  • rotating-shops.yml loses every rotating shop an earlier import added and gets this import's, import-report.txt is written, and the shop reloads.
  • The reply gives the sections, items and rotating shops imported, how many earlier imported rotating shops were removed, the backup folder, the report and the first 5 skipped lines.
  • dry-run reads and reports everything and writes nothing. replace is still accepted and changes nothing, because an import always replaces. Any other extra word gives the usage line.
  • from: reads a folder you copied in, as a path from the server folder or an absolute one. GrimsShop's own folder, and anything inside it such as backups/, is refused. Its sections/ and shops/ look like EconomyShopGUI's, so this stops an import of the shop into itself.
  • What comes across:
  • sections in their order, with their names and icons, and sub-sections;
  • items with names, lore, enchantments, potions, spawner mobs, heads, custom model data and item components;
  • buy and sell prices per bundle.
  • Currency: prices are in defaults.category-currency when that is a money (VAULT) currency, else in the first money currency in currencies.yml. With none, the import is refused until you add one (/shop admin currency add-vault <id>).
  • The old layout: each item keeps its page and chest slot, and each section tile keeps its main-menu slot (or its slot on its parent's page). Sections are numbered order: 1..n in the source's order under each parent. A slot that is one of GrimsShop's buttons, or already taken, moves to the next free one. The buttons are the bottom row's back, sell, previous, info, next and close. Hidden sections (NPC-only shops) stay hidden, and /shop <id> still opens them.
  • IDs: section IDs are the source's names in lower case.
  • One that is a /shop command word gets _shop added (admin_shop).
  • A rotating shop's pool gets _pool, and a repeated ID gets _2, _3 and so on.
  • Every ID stays within 40 characters.
  • Plain items keep the default sets' IDs (oak_log), so rotating shop pools keep working.
  • Parents: a section with only sub-sections is kept as their parent. A section with nothing to import in it or below it is left out and listed in the report.
  • Rotating shops (EconomyShopGUI) come across as real rotating shops in rotating-shops.yml.
  • Each keeps the source's timer, lineup size and tile slot, and is marked imported-from: <plugin>.
  • The shop sells its section's items, which become a pool-only section.
  • Minute timers stay minutes: a 20-minute shop rotates every 20m. Timers outside GrimsShop's 1m-120m, 1h-24h or 1d-31d ranges are rounded into them (under a minute becomes 1m), with a line in the report.
  • Every import first takes out every rotating shop an earlier import marked, whichever plugin it came from, because the sections it sold from are in the sections/ and shops/ being replaced. So a re-import replaces tavern instead of adding tavern_2, and an EssentialsX import after an EconomyShopGUI one leaves no shop selling from sections that are gone. /shop admin defaults takes them out too.
  • Your own rotating shops (no imported-from: line, such as the Quick Market) always stay. The removed ones are in the backup's copy of rotating-shops.yml.
  • To keep an imported shop, delete its imported-from: line in rotating-shops.yml before the next import or defaults swap. Pool items the new shop doesn't have are then skipped.
  • Rotating shops over rotating-shops.max (4, counting the ones that stay in rotating-shops.yml) become normal sections, and the report says so.
  • Custom items: supported pack-host integrations can supply shop items. An unmodified pack item is saved by its plain ID, such as custom: "egw_clothes:weekend_tee", with match: exact so pack updates reach it. Other items are captured as item-data.
  • What doesn't come across, and is listed in import-report.txt:
  • Command, rank and permission products.
  • Display-only and navigation buttons.
  • Prices in currencies other than money.
  • Custom items from plugins that aren't installed.
  • Stock limits, dynamic pricing and discounts.
  • EssentialsX sell multipliers and sign prices.
  • import-report.txt sits in plugins/GrimsShop/. Its first line names the backup folder, so the way back is the first thing you read. To undo an import, see Backups, and going back.

EconomyShopGUI sub-sections

EconomyShopGUI 6 on a 26.x server writes a nested default shop. Main sections such as Building hold only link buttons, and each link opens a sub-section kept in a subfolder (sections/Building/stone.yml with shops/Building/stone.yml).

  • Subfolders are read, and a section pairs with its shop file by file name, as in EconomyShopGUI. If two files share a name, one is kept and the other is in the report.
  • Link buttons (items with section: <name>) make the section they open a sub-section of the section they sit in. Its tile sits where the link sat, with the link's name and picture.
  • One place each: the first link to a section wins. Later links, links to missing or switched-off sections, links to main-menu sections and links that would loop are in the report.
  • Unlinked sub-sections (such as Z_EverythingElse) become hidden sections that /shop <id> opens.
  • Item layouts: items without a slot: fill the 1 cells of the section's item-layout, page by page, as EconomyShopGUI shows them. An item EconomyShopGUI never showed (page full, unreadable slot) gets a free slot and a report line.
  • A fresh 6.3.1 install on 26.2 gives 27 sections and 1504 items: the 10 main sections in their menu slots, 16 sub-sections and the hidden z_everythingelse. Its 77 spawn eggs are left out, because EconomyShopGUI ships that section switched off.
  • The flat 1.21 default gives 15 main-menu sections, 930 items and its RotatingShop as a rotating shop. Its Commands section is left out, because every item in it runs a command.
  • Slot numbers: EconomyShopGUI counts tile slots from 1 since Premium 5.21 and free 6.11, and from 0 before. The version comes from the EconomyShopGUI jar in plugins/ (or next to a from: folder). Without a jar, subfolders or an item-layout mean counting from 1.

EssentialsX worth.yml

worth.yml only has sell prices, with no menu, pages or slots.

  • Every listing is sell-only, priced per single item, and sorted into the every-block set's sections. Add buy prices by hand.
  • Keys EssentialsX pays on this server come across at the same price.
  • Pre-1.13 names that the stock file still ships (log, wool, sulphur, goldchestplate...) come across as the items they priced before 1.13. wool gives all 16 colours, and log the four old logs. EssentialsX on 1.13+ never paid for these, so GrimsShop now buys items its /sell refused. Each one has a line in the report; delete the listings you don't want.
  • Renamed names come across as the new item: grass as short grass, sign as an oak sign.
  • Two keys for one item: the newest name wins, and a key set to -1 keeps the item unsellable.
  • Skipped: names of blocks that were never items (stationarywater, irondoorblock...).
  • The stock EssentialsX 2.22.1 file gives 232 items from 155 of its 166 keys. The other 11 are in the report.

The main menu

/shop is one double-chest screen:

  • Row one (slots 0-8) is for rotating shops. The Quick Market sits at slot 4, the top middle.
  • Slots 9-44 hold the main sections (those without a parent:), sorted by order: and then by ID. More sections than slots add pages. A section with a slot: sits there instead (see Fixed positions).
  • The bottom row has previous page, sell, close and next page.

Sub-sections sit on their parent's page instead (see Sub-sections). /shop <section> opens a section or sub-section directly, e.g. /shop farming. Slots and buttons live under main-menu: in layouts.yml.

To group sections behind one main-menu tile, as 0.3.0's shop-sections.yml did, make a section with no items and give the others parent: with its ID. The drop-ins' Custom tile is built that way.

The Custom drop-ins

GrimsShop-0.4.2-DropIns.zip (in dist/) puts every custom item from EGW's plugins and packs in the shop, under one Custom tile on the main menu. Its sections/ and shops/ folders sit at the zip's root. Unzip it into plugins/GrimsShop/, where they merge with yours (a file with the same name is replaced), and run /shop reload.

  • When to unzip. Only after 0.4.0 has started once: while sections/ or shops/ exists, the defaults are never written. /shop admin import and /shop admin defaults replace sections/ and shops/ whole, drop-ins included, so the Custom tile goes to backups/<...>/ with the rest (nothing is lost). Unzip again afterwards. In 0.3.0 the drop-ins survived imports and preset switches; in 0.4.0 they don't.
  • Unzipped too early? If you unzipped before the first start, the shop holds only the drop-ins and no defaults. Run /shop admin defaults every-block (or the import), then unzip the drop-ins again.
  • The Custom tile is sections/custom.yml, at main-menu slot 40, which is free with every default set. An import may already use slot 40 (EconomyShopGUI 6.3.1's Misc does): then one of the two takes the next free slot and /shop validate warns. Right-click the Custom tile and change its slot to put it somewhere else. Its eight sub-sections (parent: custom, order: 1 to 8) are, in order:
  • Clothing: converted from the Grims Clothes Pack's own shop file.
  • Armor & Weapons: the five EGW Armored sets, Dreadplate Regalia, Amethyst and Emerald gear.
  • Nilla Fishin: fish by rarity, realm fish, tackle, gear and sushi.
  • Deep Discoveries: gems, the three Prospector's Pickaxes and the journal.
  • Redstone Wifi.
  • Vouchers: 5 chest, 5 backpack and the Walkman.
  • Brewery: the 16 Fermentation & Aging drinks, made by GrimsCrops 0.15.5 or later.
  • Super Spawners: Level 1 to 5, one spawner per mob GrimsSuperSpawners allows by default.

Clothing, Armor & Weapons, Nilla Fishin and Super Spawners hold sub-sections of their own. A section that only holds sub-sections has a stock file with items: {}.

  • Use plain namespace:id values for pack items. Packforge is the preferred host.
  • Taking part of it out: set enabled: false in that section's file, which also switches off the sections under it, or delete its pair.
  • Beta pricing. Every listing buys and sells for 1, so testers can grab anything; real prices come later. Each file's header says so and lists the economy caveats to settle before real prices:
  • Nilla's Fish Shop pays a bought fish's full base price (a money loop).
  • Selling fossils at 1 undercuts GDD's /dig sell.
  • Every spawner costs 1.
  • The drinks skip their stills and casks.
  • The Chest Wrench moves any upgraded chest its holder can open.
  • Gems make GDD's pick upgrades nearly free.
  • Dreadplate, gem gear, Wifi devices and the Walkman undercut their recipes.
  • Settle the fish money loop before beta. GrimsShop sells every Nilla fish for 1. Nilla's own Fish Shop pays a bought fish (a standard specimen, not a weighed catch) its full base price, 3 to 780, through the same Vault economy. Buying 64 Void Monarchs for 64 and selling them in /gnf pays 49,920, and nothing in GrimsShop stops it at beta prices. Pick one fix before testers play:
  • take the fish listings' buy: off until real prices;
  • set GrimsNillaFishin's economy.mode: internal, so its Fish Shop pays Fishing Coins instead of server money;
  • or price each fish at or above Nilla's base price.
  • Left out: crop shop items, the chests and backpacks themselves (their vouchers are sold), pack look-alikes of plugin items, admin and test items, the casino's golf gear, packs that are not installed, the JukeBoxes devices, and the Trick Hook.
  • Spawners made with /shop admin superspawners. The Super Spawners sections use the listing IDs that command writes (superspawner_zombie_l3). A server that followed SUPERSPAWNERS-SETUP.md already has some of them in shops/superspawners.yml.
  • Item IDs are unique across shops/, so each spawner ID in both is left out of the stock file that loads later (files load in name order), with a catalog-left-out error naming both files. With SUPERSPAWNERS-SETUP.md's superspawners section, the drop-in's super_spawners_l*.yml files load first, so the command's copies are the ones left out.
  • With the default 85 mobs, that is 255 errors for levels 1, 3 and 5.
  • Pick one. Before unzipping, delete the command's section, which is its two files sections/superspawners.yml and shops/superspawners.yml. Or keep it, and after unzipping switch the drop-in's Super Spawners off with enabled: false in sections/super_spawners.yml: switched-off items clash with nothing.

Sell-only shops (the fossil buyback)

Fossils are on no menu, but /sell all, /sell hand and the sell chest still buy them. That needs nothing new. Quick-sell uses every section the player may use, hidden ones too, and a listing with only sell: is never sold. The drop-ins' fossil_buyback pair is that pattern:

# sections/fossil_buyback.yml
name: "&7Fossil Buyback"
icon: {custom: "discoveries:fossil:ammonite"}
hidden: true                       # on no menu and no page; /shop fossil_buyback still opens it, sell prices only

# shops/fossil_buyback.yml
items:
  fossil_fern:
    name: "Ancient Fern"
    item: {custom: "discoveries:fossil:fern"}
    sell: 1                        # no buy: the shop never sells one

It holds every whole fossil and fragment of the gdd, dino and birdop packs. The dino and birdop ones resolve only once dino.yml and birdop.yml are in plugins/GrimsDeepDiscoveries/fossils/ and the shop has reloaded since. Run /dig packs reload, then /shop reload (or restart); GrimsShop is not told when GDD reloads its packs. Until then each one is a warning and is not bought.

Regenerating the drop-ins

The files are generated, never hand-edited. tools/custom-dropins/generate.py (Python 3, standard library only) builds them from:

  • docs/custom-items-survey-2026-10-12.json: every item marked include: true;
  • tools/custom-dropins/inputs/: the five Armored sets, and the spawner mob list;
  • the Grims Clothes Pack's own grims-clothes.yml, which it splits into section pairs with plain IDs. The Clothes Pack itself is not touched.

From the GrimsShop folder:

python3 tools/custom-dropins/generate.py --report     # rewrites src/test/resources/dropins/ (sections/ and shops/); --report lists what is left out and why
(cd tools/custom-dropins && java -cp ~/.gradle/caches/modules-2/files-2.1/org.yaml/snakeyaml/2.2/*/snakeyaml-2.2.jar tools/Validate.java)
./gradlew build dist --offline                        # DropInsTest loads them; dist/ gets GrimsShop-<version>-DropIns.zip and its SHA256
  • Running it twice gives the same files, and any other .yml left in the output folders is removed. A survey item marked include: true that it neither lists nor names in its skip lists stops it, so nothing new is dropped silently.
  • Use plain namespace:id values for pack items and icons. Do not add a host prefix. EGW gameplay-plugin prefixes such as fishin: and spawners: remain necessary.
  • inputs/spawner-mobs.txt is GrimsSuperSpawners' default rule (living, spawnable, has a spawn egg, not denied) applied to the Paper API the shop builds against. (cd tools/custom-dropins && java -cp "$(tools/paper-classpath.sh)" tools/SpawnerMobs.java) prints it again.
  • Regenerating overwrites what was changed in game in those files (prices, names). Change the generator or its inputs instead, or price in game after the last regeneration.

Custom pack items

Anywhere a shop file takes an item, it also takes custom: with a plugin's own item ID:

item:
  custom: "egw_clothes:weekend_tee" # plain namespace:id

That covers items and their icons, section and rotating shop icons, and layout fillers. EGW's own files (the drop-ins, the packs' shop files) use plain IDs for every pack item.

  • A plain namespace:id asks Packforge first. Supported fallback hosts can resolve the same ID when Packforge is absent.
  • Plain IDs contain one colon. Reserved host and EGW plugin prefixes are interpreted as integrations, not pack namespaces.
  • There is no exception for minecraft:: custom: "minecraft:stone" asks Packforge and gives a warning. Use material: STONE.
  • An ID that is neither plain nor prefixed (custom: "weekend_tee", or nexo: in a shop file, which only imports read) leaves that item out with an error.
  • Older host-prefixed IDs remain a compatibility feature. Use plain namespace IDs for new pack-item entries.
  • From your hand. These save a supported pack-host item by its plain ID when it is exactly as its pack makes it: Add the item in your hand, /shop admin item add-hand and Replace item from hand.
  • The ID is checked by making the item again and comparing it with the one you hold.
  • The listing gets no name:, so it shows the pack's own name and follows pack updates, and match: exact is written out.
  • Replace item from hand keeps the listing's match when it still fits the new item. When it doesn't (a pdc: or custom model data match the pack item lacks, say), an unchanged pack item gets match: exact, so selling back never quietly loosens to item model.
  • A renamed or otherwise changed copy, and any other item, is captured exactly as item-data.
  • When a host cannot recreate the exact item from its ID, the held stack is captured instead.
  • Icons, layout fillers and currency items set from your hand are always captured.
  • Always fresh. The file keeps the ID, and the item is built by its plugin every time the shop loads; nothing is captured. A pack update (new lore, a new model) reaches the shop at the next load. Editing prices, stock, the name or the section in game keeps custom: as it is. Only Replace item from hand swaps it for the held item.
  • Items belonging to a host that is still loading remain pending and hidden until the host is ready.
  • The shop reloads after a supported content host reports that its items have loaded.
  • Packforge loads its items while it enables and then registers its items service. That registration is its ready signal, and the shop reloads then too.
  • Only a shop that names custom items reloads. /shop validate and /shop reload say how many items are still waiting.
  • After that, an ID the plugin does not know is a warning naming the file and key, and the item is hidden like an item from a newer Minecraft version. An icon falls back to the default (a chest, a clock, the item itself) instead.
  • Plugin not installed: its items are hidden, with one warning for all of them.
  • A plugin whose jar is there but that is disabled (its startup failed) counts as not installed. It will never load its items, so they are not left waiting.
  • With neither plugin, a file of plain or pf: items gives one "Packforge is not installed" warning.
  • Rotating shops wait too. A rotating shop whose pool holds items still waiting for their plugin keeps them in its lineup and shuffle. It draws, rotates and saves nothing until the shop reloads with them; a rotation that falls due in that window happens then. So a restart never reshuffles custom items out of a lineup. A plugin that has still not loaded after 10 minutes is not waited for any longer: the shop rotates without its items, as for any missing item.
  • Selling back. An item with custom: and no match: matches by item model (item-model), or by custom model data when the item has no model, so worn, renamed or re-lored copies still sell. An EGW plugin's own item matches by that plugin's identity key instead (see the table below). An explicit match: wins; picking exact in the editor writes match: exact. Replace item from hand writes the default match out, so it stays when the item is no longer a custom: one.
  • Bedrock pictures. Touch-form buttons show an supported pack-host item's picture from textures/items/<namespace>/<id>, where the EGW pack builder puts it (textures/items/egw_armored/emberforge_helmet). A form-image: still wins.
  • An item currency must exist when the shop opens, so custom: is not supported for currencies. Hold the item and use Item in hand instead.

Items the EGW plugins make

Some EGW plugins make their own items and mark each with a data key of their own; the plugin ignores anything without it, so a pack's copy of such an item only looks like it. For these, custom: takes the plugin's own prefix, and GrimsShop asks the plugin itself to make the item:

PrefixPluginExampleFormsSells back by (no match:)
fishin:GrimsNillaFishinfishin:koia fish or tackle id, copper_rod, iron_rod, trap_3 to trap_18 (in steps of 3), sushi_station, a sushi dish idfish, tackle and rods pdc:grims_nilla_fishin:item_id; dishes pdc:grims_nilla_fishin:dish_id; traps pdc:grims_nilla_fishin:trap_capacity; the station pdc:grims_nilla_fishin:sushi_station. Never a test fish or a weighed catch
discoveries:GrimsDeepDiscoveriesdiscoveries:gem:ruby`gem:<ruby\sapphire\cats_eye\rock_crystal>, pickaxe, pickaxe:emberforged, pickaxe:stonebinder, journal, fossil:<full id>, fragment:<full id>:<part> (a full id is fern for the built-in pack, dino:tyrannosaurus_rex` for another)gems pdc:grimsdeepdiscoveries:gem; whole fossils pdc:grimsdeepdiscoveries:species; fragments item-model (exact while GDD's own item models are off), with GDD's own kind, species and part; the journal and the three pickaxes pdc:grimsdeepdiscoveries:kind, each pick with its own upgrades
chests:GrimsChestschests:voucher:jack`voucher:<jack\christmas\wrench\remote\core>`pdc:grimschests:chest_voucher
backpacks:GrimsBackpacksbackpacks:voucher:soul_coffin`voucher:<standard\halloween\christmas\soul_coffin\cursed_spellbook>: the stored style ids, not the command's basic, coffin and spellbook`pdc:grimsbackpacks:backpack_voucher
jukeboxes:GrimsJukeBoxesjukeboxes:walkman_voucherwalkman_voucher onlypdc:grimsjukeboxes:object_type
wifi:GrimsRedstoneWifiwifi:sender_componentsender, receiver, transponder, diode, smart_repeater, sender_component, receiver_component, transponder_componentpdc:trickswireless:item
crops:GrimsCropscrops:beera GrimsCrops item id, as /gcrops give takes it (beer, whisky_aged, pink_donut); needs GrimsCrops 0.15.5 or later (see below)pdc:grimscrops:item_id
spawners:GrimsSuperSpawnersspawners:zombie:3<mob>:<level>spawner (this mob at this level)
  • Made by the plugin, never copied. GrimsShop calls the plugin's own public classes (by reflection, so it needs none of them to start; GrimsSuperSpawners and GrimsCrops through the API each publishes, which GrimsShop does not bundle either), never its give command, which could not say it failed, and never a copy built by hand, which would drift the day the plugin changes. Each plugin is an optional soft dependency, so it loads before GrimsShop.
  • Made again for every sale. The shop's own copy is only for its menus. A purchase asks the plugin again, once per stack handed out, so items with an identity of their own are never shared: every Nilla rod gets its own rod_id, and every fossil its own specimen. A bought fossil is unrevealed, with a hidden quality rolled at GDD's own mining odds, like a dug one; a bought fragment is Crumbling.
  • Selling back works as the table says, so a renamed or worn copy still sells, but only as its own kind: a koi never sells as a bass, a 6-catch trap never as a 9-catch one, a Jack voucher never as a Wrench one, a level-3 spawner never as a level-1. On top of its match, the item has to carry its plugin's telling tags as the shop's own copy does, whatever match: says:
  • The three Prospector's Pickaxes share their kind and differ only in their upgrade tags, so each sells back only as itself (plain, Emberforged or Stonebinder), whether or not it is worn, enchanted or renamed. A pick with both upgrades matches none of them.
  • A Nilla fish sells back only as the standard specimen the shop sells. An admin's test fish (which Nilla refuses too) never does, and nor does a weighed catch: /sell all and the sell chest leave real catches for Nilla's own Fish Shop, which prices them by weight.
  • A fragment needs GDD's own kind, species and part as well as its model, so a pack's look-alike (/pf give, the content host’s browser, Bedrock creative) is never bought as one.
  • Waiting and missing. These plugins make items as soon as they are enabled. One that is installed but not enabled yet while the server starts is pending, and the shop reloads when it enables. One still not enabled once the server has started (its startup failed) is not installed: its items are hidden, with one warning for all of them. So is a GrimsSuperSpawners that is enabled but has its spawner service paused or not registered: one warning for all its spawners, until it is back and /shop reload is run. A GrimsCrops that is enabled with no item table for other plugins is the same: one warning for all its items. An id the plugin does not know (a voucher kind it has not got, a mob or level GrimsSuperSpawners refuses, an item id GrimsCrops does not define) is a warning naming the file and key, and the item is hidden.
  • While the plugin is away. A listing whose plugin has stopped shows no buy buttons (the console says which plugin, once, as plugin-item-unavailable). If the plugin fails while making a bought item, the sale is refused before anything is charged, with trade.item-unavailable in messages.yml and plugin-item-sale in the console. Selling back keeps working, because the item says what it is.
  • GrimsCrops makes its items through its item table, which its service has handed to other plugins since GrimsCrops 0.15.5. A crops: item is the same stack /gcrops give hands out: its name, lore, food values and grimscrops:item_id tag. On GrimsCrops 0.15.4 or older there is no table, so every crops: id is hidden, with one warning for all of them (GrimsCrops is enabled, but has no item table for other plugins (it needs 0.15.5 or later)). Update GrimsCrops and run /shop reload. The Brewery drop-in's 16 drinks are GrimsCrops' own items, so they need nothing else. One difference from /gcrops give: the table also makes a dormant crop's seed and produce (hop_seeds and hops without the Fermentation and Aging add-on), which give refuses, so only list crop items that are live on your server.
  • GrimsJukeBoxes keeps its item service to itself, so GrimsShop builds one the way the plugin's own startup does (its settings, then the service for the GrimsJukeBoxes plugin) to make the Walkman Voucher. It builds it once each time GrimsJukeBoxes starts, not once per voucher, because reading those settings logs any bad value in GrimsJukeBoxes' config.yml under GrimsJukeBoxes' name. Its MP3 Player, Boom Box and Big Jukebox are owner-bound and have no voucher, so there is no form for them.

Rotating shops

Rotating shops are optional, and live in rotating-shops.yml (called shops.yml before 0.4.0; its root key is still shops:). The bundled file has one example, the Quick Market (3 hours, slot 4). Delete it and /shop shows just the sections. Up to 4 can exist (rotating-shops.max in config.yml).

Create one:

/shop admin newshop "<name>" [slot] [true|false] [timer] [lineup]
/shop admin newshop "&6Night &eMarket" 2 true
  • Name: & colour codes (&6, &l, &#ff8800) or MiniMessage. Use quotes when it has spaces.
  • Slot: the main-menu slot, 0-53, where 0 is the top-left and 4 the top middle. A missing, taken or button slot uses the first free one, going from the top middle outwards.
  • true/false: whether players see it. Staff (grimsshop.staff) always see every shop, and hidden shops are marked (hidden) for them.
  • Timer and lineup: optional, 24h and 5 items by default. A timer is 1m-120m, 1h-24h or 1d-31d (30m, 90m, 3h, 7d), and stays as you typed it.
  • Pool: a new shop draws from every priced item in every loaded section (pool: all). In the editor, Rotation pool lets you pick items section by section, and Use every priced item switches back. A pool lists item IDs; IDs the shop doesn't have (an item hidden on this server, or one in a switched-off section) are skipped.

The editor's shop page covers settings (name, slot, visible, layout, permission, timer, lineup, broadcast), pool, hide/show, icon, Bedrock picture, Rotate now, Reset rotation, Restock and delete.

  • Everyone sees the same lineup, and every priced pool item shows once before any repeats.
  • Limited stock refills with each new lineup.
  • Changing the timer only moves the next deadline. A timer shorter than the time since the last rotation puts that deadline in the past, so the shop rotates right away, and /shop admin rotation timer says so.
  • Checks: shops are checked every rotation.check-seconds in config.yml (5 by default), so a 1m shop changes within a few seconds of its deadline. A check with nothing due costs next to nothing, and a late check never shifts the schedule.
  • Catch-up: rotations missed while the server was off are caught up at startup in one step: one new lineup with fresh stock and one announcement, with the timer still on its original beat. A 1m shop that was off for a week doesn't replay 10,000 lineups.
  • Permission (optional): only players with it can open the shop, see it, or get its broadcasts.

Rotation broadcasts

Each rotating shop announces its new lineup. Set it in the shop's settings, or in rotating-shops.yml:

  quick-market:
    broadcast:
      enabled: true
      message: '<aqua>✦ Quick Market</aqua> <gray>restocked! <white>{items}</white> are in for <white>{next}</white>.</gray>'
  • Placeholders: {shop}, {id}, {next} (time until the next change) and {items} (the new lineup).
  • No message: without one, rotation.broadcast in messages.yml is used.
  • Who hears it: players who can see the shop. A hidden shop announces to staff only.
  • Turning it off: enabled: false for one shop, or rotation.broadcasts: false in config.yml for all.

Adding and editing items

Right-click any item in /shop to open it in the editor: prices, bundle, stock, currency, matching, section (the editor's Category) and position.

To add a new item:

  1. Hold the exact item: a supported pack-host item, a named sword, anything.
  2. Open /shop admin, then Items, then Add the item in your hand. Or open a section under Categories first to add straight into it.
  3. Fill in:
  4. ID
  5. Category
  6. Buy price (empty = players can't buy it)
  7. Sell price (empty = the shop doesn't buy it)
  8. Bundle size
  9. Match
  10. The item joins the end of its section's shops/<id>.yml. With no prices it is a hidden draft until you price it. A supported pack-host item exactly as its pack makes it is saved by its plain ID (see Custom items); anything else is captured exactly.

A price on one side only is fine and shows exactly one button: buy-price-only items are sold and never bought back, sell-price-only items are bought back and never sold. See When an item shows no buttons below for the other reasons a priced item can stop offering a side.

Command line: /shop admin item add-hand <section> <id> [buy] [sell] and /shop admin item price <id> <buy|sell> <amount|none>.

In YAML, an item can be a material with an optional potion or enchantments, a skull, captured item-data or a custom: ID:

# shops/brewing.yml
items:
  potion_long_swiftness:
    name: Potion of Swiftness (Extended)
    item:
      material: POTION
      potion: long_swiftness
    buy: 11.5
    sell: 2.88

Items this server's Minecraft version doesn't have are hidden with one console warning instead of an error.

Fixed positions

Items fill their section in order unless they are pinned. Sections fill the main menu the same way, sorted by order:.

# shops/farming.yml: page 1, slot 13 of the section's chest
items:
  carrot:
    page: 1
    slot: 13

# sections/farming.yml
slot: 9               # main-menu slot

# sections/staff_tools.yml
hidden: true          # off the main menu; /shop staff_tools still opens it

# sections/tavern_pool.yml
pool-only: true       # never browsable; only sold through a rotating shop
  • Slots count from 0 at the top left. Pages count from 1.
  • Taken or button slots: a pinned slot that is taken, is one of the bottom-row buttons or doesn't exist moves to the next free one, with a warning from /shop validate.
  • Sub-section tiles use page and slot the same way on their parent's page (see Sub-sections).
  • Phones: touch forms list items and sub-sections in the same order the chest pages show them.

Matching (selling)

When players sell, their items must match the listing.

MatchUse for
Exact (default)Everything must match: name, lore, enchantments, damage, all data.
Custom item modelCustom items whose per-item data varies. Only the item model is compared.
Custom model dataOlder custom items that use custom model data.
Spawner mobSpawners. Only the mob is compared, so a mined spawner sells back however it was named. With SilkSpawners installed, Exact spawner listings are traded this way too (see SilkSpawners). On a GrimsSuperSpawners spawner it compares the mob and the level, and only its own plugin's spawners can match (see GrimsSuperSpawners).
ID tag (PDC)Items with an ID key, e.g. grims_nilla_fishin:item_id. Only that key's value is compared. A GrimsSuperSpawners spawner is the one item this is never offered for: each of its tags describes only part of the item (see GrimsSuperSpawners).

An item from a custom item ID with no match: uses Custom item model (or Custom model data, if it has no model) rather than Exact. An item an EGW plugin makes uses that plugin's ID tag instead, as listed in Items the EGW plugins make.

In YAML the modes are exact, item-model, custom-model-data, spawner and pdc:<namespace>:<key>:

# shops/spawners.yml
items:
  spawner_zombie:
    item: {item-data: '...'}
    buy: 100
    match: spawner

SilkSpawners

GrimsShop works with SilkSpawners_v2 (the fork by CandC_9_12) when it is installed, and changes nothing when it is not.

  • Reading the mob: SilkSpawners keeps a spawner's mob on the item itself, not on its block state. GrimsShop reads both, so phone menus, chest lore (Spawns:) and default item names always name the right mob, with or without the plugin.
  • Matching by mob: while SilkSpawners is installed, a spawner listing on Exact is traded by mob instead: any spawner of that mob sells to it, whatever it was named, and the shop hands out SilkSpawners' own item for that mob. Both halves move together, so nobody is ever handed a spawner the shop then refuses to buy back. Nothing has to be migrated: it applies to listings an importer or a default set already wrote. Trial spawners are never touched, and neither is a listing on any other match mode.
  • Buying: a listing whose spawner is a plain one (the default sets, an EconomyShopGUI import, anything from /give or the creative menu) is handed out as SilkSpawners' own item for that mob. Without this, SilkSpawners would place it as the server's default mob instead of the one the shop showed. Spawners SilkSpawners already made are handed out untouched, and so is everything else if its API is missing or fails. Turn it off with silkspawners.convert-purchases: false in config.yml.
  • Selling: an Exact spawner listing buys back by mob as above, and a listing you put on Spawner mob yourself always does, whatever the toggles say: it buys any spawner of that mob, whether it came from SilkSpawners, a block-state spawner or a rename. A spawner holding a mob this server does not have (a modded one, or one a downgrade removed) keeps that name, so it never sells at the empty-spawner price.
  • The toggle: silkspawners.match-by-mob: false in config.yml turns both halves off together. Exact spawner listings are then neither converted on purchase nor matched by mob, so the shop hands out its own item and buys exactly that item back. Use it only if you want the shop's own spawners traded verbatim.
  • Stocking a listing by hand: hold a /silkspawners give <mob> item and use /shop admin item add-hand <section> <id> [buy] [sell], then set its match to Spawner mob in the editor. The listing then holds SilkSpawners' own item and needs no conversion at all.
  • Filling a section: /shop admin spawners <section> [buy] [sell] adds one item per mob SilkSpawners supports, using its items and names, at bundle 1 and matched by mob.
  • Mobs the section already sells are skipped. Items are spawner_<mob>, or spawner_<mob>_<section> when another section took that ID, so the same mob can be sold in several sections. An ID held in a switched-off section's stock file, or in a stock file without its section file, counts as taken too; the reply counts mobs that were already there and mobs with no ID left to take apart.
  • With no prices the new items are drafts: they stay hidden until you price them in the editor (or with /shop admin item price <id> buy <amount>).
  • With a buy price, every item gets it, and the sell price follows the default sets' 25% rule unless you give one.
  • All of it is written in one go and checked like any other change, so a batch that would break the files changes nothing. The SuperSpawners generator also aborts without saving if the provider fails during the run or returns an invalid item.
  • It needs grimsshop.admin.item, and refuses with a clear message when the section is unknown or SilkSpawners is missing — including when it is installed but its API answers nothing, which is the same thing from the shop's side.

GrimsSuperSpawners

GrimsShop also works with GrimsSuperSpawners, whose spawners are owned, stackable and levelled: a level-3 spawner is one item that takes three spawner slots of its owner's allowance when it is placed. Nothing changes when the plugin is not installed, except that listings selling its spawners are not handed out (see Buying below).

  • What is supported: selling and buying back its spawners at any level, one listing per mob and level, with the level shown everywhere a mob is shown, and filling a section with one level in one command (see Filling a section below). What is not: choosing the levels for you, because which levels a server sells, and at what price, is its own decision.
  • Each level is its own item. A listing holds one mob at one level, and nothing else can pay for it: not another level of the same mob, not another mob at the same level, and not a plain or SilkSpawners spawner. A level-5 listing is never handed out as five level-1 spawners, and a bundle of two level-3 spawners is two items (six slots once placed), not a level-6.
  • Reading the mob and level: they travel on the item itself, so chest lore, phone menus and default item names read Spawns: Zombie and Level 3 (3 slots when placed) with or without the plugin running. The item's existing custom name is preserved; when it has none, the default is "Zombie Spawner (Level 3)". Mob and level are also shown in item details.
  • Adding one listing: hold the item — /gss give makes one, and so does taking one back out of the world — and use /shop admin item add-hand <section> <id> [buy] [sell]. Leave the match on Exact unless you want renamed copies to sell back, in which case pick Spawner mob, which for these items means "this mob at this level, however it was named". Repeat per level, with its own price each time.
  • Filling a section: /shop admin superspawners <section> <level> [buy] [sell] adds one item per mob GrimsSuperSpawners allows, at that one level, using its own items and names, at bundle 1 and matched Exact so no level can ever pay for another.
  • Levels are per listing, and per run. superspawners spawners 1 500 then superspawners spawners 3 4500 gives the section both levels at their own prices. Items are superspawner_<mob>_l<level>, or superspawner_<mob>_l<level>_<section> when another section took that ID, so the same mob and level can be sold in several sections. An ID held in a switched-off section's stock file (the drop-ins' Super Spawners with enabled: false, say), or in a stock file without its section file, counts as taken too.
  • Mobs already sold here at that level are skipped, whatever their listings are called — it compares the item's own mob and level, not the ID. Another level of the same mob is a different item, so it is still added.
  • The three counts in the reply. GrimsSuperSpawners' API names neither the mobs it allows nor the server's level cap, so the shop offers it every mob a spawner could hold and keeps what it accepts. The reply counts, apart: mobs the section already had at that level (nothing to do), mobs the plugin refused (its own mob list and level cap — usually most of them, and nothing to act on), and mobs with no listing ID left to take (rename or remove whatever holds those IDs). Refusals are ordinary, so nothing is written to the console about them.
  • A level above the cap shows up as every mob refusing it, which is what the reply then says: pick a lower level. There is no cap to read, only an answer per mob.
  • With no prices the new items are drafts: they stay hidden until you price them in the editor (or with /shop admin item price <id> buy <amount>). With a buy price, every item gets it, and the sell price follows the default sets' 25% rule unless you give one (none or - means the shop never buys that level back).
  • All of it is written in one go and checked like any other change, so a batch that would break the files changes nothing. The SuperSpawners generator also aborts without saving if the provider fails during the run or returns an invalid item.
  • It needs grimsshop.admin.item, and refuses with a clear message, having written nothing, when the section is unknown, the level is not a positive whole number, or GrimsSuperSpawners is missing, paused or unreadable.
  • Never match one by its raw tags. The editor does not offer them: a levelled spawner only gets Exact and its own "any level N of this mob" option, because grimssuperspawners:mob alone would let any level pay for any other, and grimssuperspawners:schema would let any levelled spawner pay for it. Existing custom match rules still parse, but every match additionally requires a valid SuperSpawners item with the same mob and level. A raw tag or visual ID can no longer bypass that identity check.
  • Buying: the buyer is handed exactly the item the shop captured, never rebuilt and never re-levelled. It is never passed through the SilkSpawners conversion, which would tag it as a plain spawner of that mob and lose the level. A listing written as custom: "spawners:<mob>:<level>" (the Custom drop-ins) is the one exception: GrimsSuperSpawners makes that mob at that level for every sale, as it makes its other items. Buying uses none of the player's placement allowance, so a full allowance never blocks a purchase; placing it is where GrimsSuperSpawners enforces that.
  • When the plugin is away: if GrimsSuperSpawners is missing, paused after a failure of its own, or no longer recognises the item a listing holds, that listing's purchases are refused with trade.levelled-spawner-unavailable in messages.yml and a console warning naming the listing. The warning is logged once per listing, not once per click, so a player hammering a broken listing cannot bury the rest of the log; any reload of the shop (/shop reload, an edit, /shop admin defaults or an import) starts the count again, so a listing you have just fixed still reports if it is still broken. Nothing is charged, and a plain spawner is never handed out instead. Selling is unaffected: a player's spawners still sell back, because the item says what it is.
  • Nothing else changes. Plain spawners, trial spawners, SilkSpawners' spawners and every other item trade exactly as before, and no listing without one of these items ever asks the plugin anything.

Sections and currencies

A section sets the default currency for its items, and an item can override it. Right-click a section tile, on the main menu or a parent's page, to edit it.

  • Money currencies use VaultUnlocked. Pick a named currency or the provider default. Without VaultUnlocked, classic Vault's single balance is used.
  • Item currencies: hold an item, then Currencies, then Item in hand as a currency. One item is one unit, so prices must be whole numbers.

A new section shows on the main menu, or on its parent's page, once it has a priced item. /shop <id> opens a section, a sub-section or a rotating shop.

  • New sections (/shop admin category create <id> <currency> [name], or Categories, then Create, in the editor) never take an ID a section file already has (in any case), a rotating shop's ID, or a /shop command word (sell, help, admin, editor, reload, validate, status). See Editing in game saves to the files for the files it writes.
  • New rotating shops get an ID that no section file or other rotating shop uses (in any case), and never catalog or a /shop command word.
  • Hand-written clashes: if rotating-shops.yml is edited by hand so a shop and a section share an ID, you get a warning and /shop <id> opens the section. The shop still opens from its main-menu button.
  • Deleting: a section can only be deleted once it has no items (including items hidden because they need a newer Minecraft version) and no sub-sections; both its files go, each kept as a .bak. A currency can only be deleted once nothing uses it, counting every section and stock file.

Sub-sections

A section can sit inside another one. It is then a tile on its parent's page, next to the parent's items, instead of on the main menu. Sub-sections can have their own sub-sections, to any depth.

# sections/building.yml: a parent needs no items of its own (no shops/building.yml, or items: {})
name: Building
slot: 12          # main-menu slot

# sections/stone.yml
name: Stones
parent: building  # a tile on Building's page, not on the main menu
order: 1          # first among Building's sub-sections
page: 1           # Building's page 1 (the default)
slot: 12          # slot 12 of that page
  • Tiles and items share the parent's page. Pinned tiles and items keep their slots, and a tile wins when both want the same slot. Then free tiles fill in (in order:), then free items. More than fits adds pages.
  • slot and page work like an item's: slots count from 0, pages from 1. A taken, button or missing slot moves to the next free one, with a warning from /shop validate. On a main-menu section, slot: is still its main-menu slot.
  • Tiles show the icon, name, description and item count, like main-menu tiles. The count includes the items in the shown sub-sections below it. Admins right-click a tile to edit it.
  • Back on a sub-section returns to the parent's page that shows its tile, then on up to the main menu. On phones the back button names the parent (touch.button.back-parent).
  • Hidden (hidden: true): no tile on the parent's page, but /shop <id> still opens it. Pool-only sub-sections are never shown.
  • When a section shows: only when it, or a shown sub-section below it, has a priced item the player can use.
  • Permissions: a sub-section needs its own permission: and every parent's. That counts everywhere: tiles, /shop <id>, buying, selling, quick-sell and rotating lineups.
  • /shop <id> opens a sub-section directly, and tab completion offers the ones the player can see.
  • Switched off: enabled: false on a parent switches off every section under it too.
  • Problems leave the section out, with its items and the sections under it, and the rest of the shop opens: an unknown parent, a section that is its own parent, parents that loop back (a > b > a, named in the error), a pool-only parent, and a parent that is itself left out.

In the editor (where sections are called categories):

  • The Categories list shows each sub-section right after its parent, marked ↳ Stones in Building.
  • A section's page says where its tile sits and which files it is saved in, lists its sub-sections and has New sub-category here. Back goes up one level.
  • Settings also covers Parent (or Main menu), Tile slot, Page, Hidden and Pool-only. Position counts among the sections in the same place and is saved as order:. After a save, that section's /shop validate warnings are shown.
  • Moving a section to a new parent puts it after the ones already there (its order: becomes one more than theirs), in the first free slot, unless you also type a new slot and page. Hidden and pool-only stay as they were.
  • Refused, with nothing saved: a loop (Building inside Stones), a pool-only parent, a parent that is switched off itself or through any section above it, making a section pool-only while it has sub-sections, and deleting a section that still has sub-sections.

Command line: /shop admin category parent <id> <parent-id|none> moves a section onto another section's page, or back to the main menu with none. Tab completion offers only parents that work.

Quick-sell

  • /sell opens the sell chest. It sells everything with a sell price when closed and hands back the rest.
  • /sell hand and /sell all need grimsshop.sell.hand and grimsshop.sell.all, which are op-only by default.
  • Items sell in whole bundles to the first matching listing in section order, and section permissions apply, including every parent's.

Layouts

The editor changes rows, the confirm and sell screen rows, amount buttons, touch page size, quick amounts and pictures. Slot positions, including the main menu's category-slots and buttons, are set in layouts.yml.

Item details on phones. Touch forms show what a chest tooltip would: a spawner's mob (and its level, on a GrimsSuperSpawners spawner), a potion's effects and duration, a book's enchantments. The item button shows them under the name, and the item's page lists them in full. Chest menus add a Spawns: line to spawners, and a Level line to levelled ones, since Bedrock shows no spawner tooltip. The lines are touch.listing.details, touch.listing.info-detail, menu.listing.spawner-line and menu.listing.spawner-level-line in messages.yml.

Touch pictures work out of the box with no resource pack.

  • Vanilla items show the texture every Bedrock client already has. Potions, splash and lingering potions and tipped arrows show their own effect's picture.
  • Custom items from an supported pack-host ID (custom: in a shop file) use textures/items/<namespace>/<id>, where the EGW pack builder puts them. Other custom items with an item model (a plugin's own, added from your hand) use textures/items/<model name>, the naming the plugins' own Grims Bedrock packs use.
  • Anything without a known picture shows no picture rather than a broken one.
  • Your own picture: set Bedrock button picture (form-image:) on a rotating shop, section or item to a texture path or an https:// link.

Player heads for Bedrock

Heads used as icons, items or currencies are merged into plugins/Geyser-Spigot/custom_mappings/grimsshop-skulls.json. This happens after a quiet period (skull-export.delay-minutes, default 20) that restarts with each new head, and at shutdown. /shop admin skulls export writes them now. Do a full restart for Bedrock to see new heads.

Hand-editing YAML

Edit the files, run /shop validate to check them (it also lists warnings, such as hidden 26.3 items, and the switched-off sections), then /shop reload.

  • Section and stock files (sections/, shops/): a problem leaves only its own section, file or item out, so the reload goes ahead and lists it (see When a file has a problem).
  • Shared files (currencies.yml, layouts.yml, rotating-shops.yml): a reload with errors is refused and the last good version keeps running. While one of them is broken, in-game edits are refused too, with the errors listed.
  • config.yml that is not valid YAML: the reload is refused and the settings stay as they were.
  • Adding a section by hand: write sections/<id>.yml (every key is optional) and, for its items, shops/<id>.yml with an items: map, then reload. Item IDs must be new: an ID another stock file already has is left out, so a copied stock file needs its items renamed.
  • Switching a file off without deleting it: rename it to .yml.disabled, or for a section set enabled: false.
  • In-game edits read the files fresh, so your hand edits are kept even before you reload.

Command reference

/shop admin newshop "<name>" [slot 0-53] [true|false] [timer] [lineup]
/shop admin shop slot <id> <slot> | visible <id> <true|false> | pool <id> <all|item...> | delete <id> confirm | edit <id>
/shop admin defaults [every-block|survival|lite]            (/shop admin preset is the same command)
/shop admin import <plugin|list> [dry-run] [from:<folder>]
/shop admin category create <id> <currency> [name] | delete <id> confirm | edit <id>
/shop admin category parent <id> <parent-id|none>
/shop admin item add-hand <section> <id> [buy] [sell] | price <id> <buy|sell> <amount|none> | remove <id> confirm | edit <id>
/shop admin spawners <section> [buy] [sell]
/shop admin superspawners <section> <level> [buy] [sell]
/shop admin currency add-hand <id> | add-vault <id> [vaultunlocked-currency] | remove <id> confirm | edit <id>
/shop admin rotation timer <shop> <1-120m|1-24h|1-31d> | advance <shop> | reset <shop> confirm
/shop admin restock <shop|catalog> [item]
/shop admin layout rows <layout> <1-6>
/shop admin skulls export
/shop reload | validate | status

See SUPERSPAWNERS-SETUP.md for a complete setup example. Unique captured-mob eggs from SuperSpawners 0.1.1 are not supported as shop products or item currency: this shop copies templates instead of transferring original stock.