Skip to main content

Shops

Official compatibility

ElementReference
TypeWriterRequired. Use the official TypeWriter release supported by the extension release.
Related extensionsInstall the related extensions listed on this page before using entries that depend on them.

Shops

The Shops extension adds TypeWriter shops connected to GUI. A shop can sell and buy back items, apply fixed or dynamic prices, sell items against other items (barter), track stock, limit transactions, and open a quantity submenu.

Verified source module: TypeWriter-ShopsExtension. No official public release for this module is referenced here.

In practice

Start with a ShopDefinitionEntry containing one item, a fixed price, and a BUY_1 action. Add a custom layout, stock, and limits afterward.

Dependencies

DependencyRole
GUI ExtensionRequired for layouts, sessions, ShopButtonType, and submenus.
TypeWriter / BTC-CORERuntime that provides entries and the action lifecycle.
VaultAPIUsed when currency is VAULT.
Custom economyPossible with balancePlaceholder, addCommand, and removeCommand, depending on the integration.

The source uses compile-time integration with GUI and VaultAPI. Check the distributed release manifest before installing additional optional dependencies.

User guide

  1. In the Typewriter Web panel, click Add Page, then use Search bar or + to create the Shop Definition entry.
  2. Create a ShopDefinitionEntry and set title, rows, currency, and items.
  3. In items, add a ShopItemConfig with item, buyEnabled: true, and fixedBuyPrice.
  4. Choose primaryAction: BUY_1.
  5. Save the entry with a stable identifier such as weapons.
  6. Test /tw shop weapons with the typewriter.shop.open permission.

Configure the menu

A shop can use the default rendering or a custom GUI layout.

For a custom layout:

  1. Add layouts to layoutPool.
  2. Choose the main layout in mainLayoutId.
  3. Place SHOP_ITEM markers in the slots intended for products.
  4. Add BUY_1, SELL_1, BUY_MAX, SELL_ALL, NEXT_PAGE, PREV_PAGE, INFO, CLOSE, or BACK buttons as needed.
  5. For a submenu, set subMenuLayoutId and subMenuTitle.

Quantity actions

Exact actionResult
BUY_1 / SELL_1One unit.
BUY_STACK / SELL_STACKOne stack.
BUY_MAX / SELL_ALLThe maximum possible amount after checking balance, inventory, stock, and limits.
BUY_CUSTOM / SELL_CUSTOMInput dialog.
BUY_1:10 / SELL_1:10Fixed 10-unit button in a submenu.

Actions are available in primaryAction, secondaryAction, and shiftAction, or as a layout button. BUY_SUBMENU and SELL_SUBMENU route to the configured submenu.

Input dialog

To customize BUY_CUSTOM and SELL_CUSTOM, use:

FieldFunction
buyAmountPromptBuy prompt.
sellAmountPromptSell prompt.
amountConfirmButtonConfirmation label.
amountInputLabelInput label.
amountInputPlaceholderHint text.
amountInputWidthInput width.
amountInputMaxLengthMaximum length.
invalidAmountMessageMessage for an invalid amount.

The dialog accepts a positive integer. Price, stock, permissions, and limits are recalculated when the amount is confirmed.

Commands

Player

/tw shop <id>

Permission: typewriter.shop.open.

Administration

All of the following commands use typewriter.shop.admin:

/tw shop admin list
/tw shop admin info <shop>
/tw shop admin open <shop> [target]
/tw shop admin refresh [target]
/tw shop admin close [target]
/tw shop admin reset <shop>
/tw shop admin stock <shop> <itemIndex> get
/tw shop admin stock <shop> <itemIndex> set <amount>
/tw shop admin stock <shop> <itemIndex> add <amount>
/tw shop admin stock <shop> <itemIndex> remove <amount>
/tw shop admin history [target]

<itemIndex> is a numeric item index. ShopsInitializer registers typewriter.shop.open for everyone by default and typewriter.shop.admin for operators by default.

MiniMessage placeholders

Current placeholders are MiniMessage tags. The old %typewriter_shop...% forms are no longer PlaceholderService syntax.

Exact tagMeaning
<shop_name:mykey>Nom du shop.
<shop_entryid:mykey>Entry identifier.
<shop_cooldown:mykey>Temps avant le reset.
<shop_cooldown:mykey:{d}j:{h}h:{m}m:{s}s>Reset with a custom format.
<shop_buy_price:mykey:0>Buy price of item 0. Reads on a priceMode: ITEMS item.
<shop_sell_price:mykey:0>Sell price of item 0. Reads on a priceMode: ITEMS item.
<shop_stock:mykey:0>Stock courant.
<shop_stock_max:mykey:0>Stock maximum.
<shop_has_promotion:mykey:0>Promotion active ou non.
<shop_trend:mykey:0>Tendance du prix.
<shop_trend_icon:mykey:0>Trend icon.
<shop_price_delta:mykey:0>Variation du prix.

mykey is resolved first as a shop name and then as an identifier.

Lore and name tokens

These tokens are replaced in priceLore, defaultNameFormat, defaultLoreFormat and an item's name / lore before MiniMessage parsing. A line asking for an unavailable price is dropped instead of rendering empty.

Exact tokenMeaning
{item}The item's own name.
{buy} / {sell}Formatted buy / sell price. Dropped on an unbuyable / unsellable item and on a priceMode: ITEMS item.
{item_price}Price paid in items, one dash-prefixed line per requested item (- 12 × Copper Ingot). Dropped on an item that is not paid in items.
{stock} / {stock_max}Current and maximum stock.
{currency}Currency symbol.

Barter — items for items

Set priceMode: ITEMS on a ShopItemConfig and list what it costs in itemPrice (one ItemCost = item + quantity per unit bought). Several lines mean several items are required at once — one item for several, or several for several. defaultItemPrice on the shop covers every ITEMS item without its own list; an item's list replaces the shop's. Refusals use cannotAffordItemsMessage with {missing} and {amount}. Details and rules: Shop Definition.

Class relationships

ElementResponsibility
ShopDefinitionEntryDefines the shop, its items, economy, and layouts.
ShopItemConfigDefines an item, its prices, actions, limits, and criteria.
ShopInteractionConfigAssociates each action with a click type.
ShopClickActionBusiness value such as BUY_1 or SELL_CUSTOM.
ShopButtonTypeButton that can be placed in a GUI layout.
ShopGuiServiceConstruit le menu et les slots dynamiques.
ShopButtonActionHandlerTraduit shop: en action de bouton.
ShopTransactionHandlerValidates and executes prices, economy, stock, taxes, and limits.

Stock, prices, and limits

  • priceMode is FIXED, DYNAMIC or ITEMS (paid in items, see above).
  • taxMode is PER_TRANSACTION or PER_ITEM.
  • reset can be None, Cron, Interval, Daily, Weekly, or Monthly.
  • playerLimit, globalLimit, globalPlayerLimit, globalBuyLimit, and globalSellLimit bound transactions at their respective levels.
  • itemPools use items, displayCount, weight, quantity, isLimited, and limit.
  • A promotion can target a shop and a list of indices; durationSeconds: 0 means permanent.

Common errors

SymptomChecks
The menu does not openGUI installed, correct identifier, typewriter.shop.open, Vault dependency when currency: VAULT.
A button does not reactShopButtonType, buttonPrefix: shop_button:, clickPermission, GUI handler, and selected action.
No item appearsmainLayoutId, SHOP_ITEM markers, items, criteria, and layout slots.
Purchase refusedBalance, buyEnabled, price, stock, limit, inventory, and promotion.
Custom amount refusedPositive integer, amountInputMaxLength, stock, balance, and limits.
Empty placeholderExact shop name/identifier and item index; use MiniMessage syntax.

Source

Troubleshooting

The extension is not visible

Check that the installed release matches the supported TypeWriter release and that the related extensions listed in the compatibility section are present.

An entry is missing

In the Typewriter Web panel, use the Search bar or the + button to find or create the entry with its exact identifier. Entry IDs and field names are case-sensitive; do not translate them.

The entry saves but nothing happens

Check that the entry is connected to the trigger, command, objective, event, or menu interaction required by its type. Test with optional permissions and criteria removed, then add them back one at a time.

An integration does not work

Verify the dependency and version shown in the extension card, then check the server log for the first error. Do not replace a missing dependency with a similarly named plugin unless the extension source explicitly supports it.