Shops
Official compatibility
| Element | Reference |
|---|---|
TypeWriter | Required. Use the official TypeWriter release supported by the extension release. |
| Related extensions | Install 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.
Start with a ShopDefinitionEntry containing one item, a fixed price, and a BUY_1 action. Add a custom layout, stock, and limits afterward.
Dependencies
| Dependency | Role |
|---|---|
| GUI Extension | Required for layouts, sessions, ShopButtonType, and submenus. |
| TypeWriter / BTC-CORE | Runtime that provides entries and the action lifecycle. |
| VaultAPI | Used when currency is VAULT. |
| Custom economy | Possible 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
- In the Typewriter Web panel, click
Add Page, then useSearch baror+to create theShop Definitionentry. - Create a
ShopDefinitionEntryand settitle,rows,currency, anditems. - In
items, add aShopItemConfigwithitem,buyEnabled: true, andfixedBuyPrice. - Choose
primaryAction: BUY_1. - Save the entry with a stable identifier such as
weapons. - Test
/tw shop weaponswith thetypewriter.shop.openpermission.
Configure the menu
A shop can use the default rendering or a custom GUI layout.
For a custom layout:
- Add layouts to
layoutPool. - Choose the main layout in
mainLayoutId. - Place
SHOP_ITEMmarkers in the slots intended for products. - Add
BUY_1,SELL_1,BUY_MAX,SELL_ALL,NEXT_PAGE,PREV_PAGE,INFO,CLOSE, orBACKbuttons as needed. - For a submenu, set
subMenuLayoutIdandsubMenuTitle.
Quantity actions
| Exact action | Result |
|---|---|
BUY_1 / SELL_1 | One unit. |
BUY_STACK / SELL_STACK | One stack. |
BUY_MAX / SELL_ALL | The maximum possible amount after checking balance, inventory, stock, and limits. |
BUY_CUSTOM / SELL_CUSTOM | Input dialog. |
BUY_1:10 / SELL_1:10 | Fixed 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:
| Field | Function |
|---|---|
buyAmountPrompt | Buy prompt. |
sellAmountPrompt | Sell prompt. |
amountConfirmButton | Confirmation label. |
amountInputLabel | Input label. |
amountInputPlaceholder | Hint text. |
amountInputWidth | Input width. |
amountInputMaxLength | Maximum length. |
invalidAmountMessage | Message 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 tag | Meaning |
|---|---|
<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 token | Meaning |
|---|---|
{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.
Related entries
Class relationships
| Element | Responsibility |
|---|---|
ShopDefinitionEntry | Defines the shop, its items, economy, and layouts. |
ShopItemConfig | Defines an item, its prices, actions, limits, and criteria. |
ShopInteractionConfig | Associates each action with a click type. |
ShopClickAction | Business value such as BUY_1 or SELL_CUSTOM. |
ShopButtonType | Button that can be placed in a GUI layout. |
ShopGuiService | Construit le menu et les slots dynamiques. |
ShopButtonActionHandler | Traduit shop: en action de bouton. |
ShopTransactionHandler | Validates and executes prices, economy, stock, taxes, and limits. |
Stock, prices, and limits
priceModeisFIXED,DYNAMICorITEMS(paid in items, see above).taxModeisPER_TRANSACTIONorPER_ITEM.resetcan beNone,Cron,Interval,Daily,Weekly, orMonthly.playerLimit,globalLimit,globalPlayerLimit,globalBuyLimit, andglobalSellLimitbound transactions at their respective levels.itemPoolsuseitems,displayCount,weight,quantity,isLimited, andlimit.- A promotion can target a shop and a list of indices;
durationSeconds: 0means permanent.
Common errors
| Symptom | Checks |
|---|---|
| The menu does not open | GUI installed, correct identifier, typewriter.shop.open, Vault dependency when currency: VAULT. |
| A button does not react | ShopButtonType, buttonPrefix: shop_button:, clickPermission, GUI handler, and selected action. |
| No item appears | mainLayoutId, SHOP_ITEM markers, items, criteria, and layout slots. |
| Purchase refused | Balance, buyEnabled, price, stock, limit, inventory, and promotion. |
| Custom amount refused | Positive integer, amountInputMaxLength, stock, balance, and limits. |
| Empty placeholder | Exact 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.