Aller au contenu principal

Shops

Menus de boutique avec prix fixes, dynamiques ou de troc, stock, limites, taxes et trois types de monnaie.

Gratuitesv1.12Économie et artisanat
NécessiteTypeWriter0.9GUI0.17+VaultfacultatifPlaceholderAPIfacultatifDiscordfacultatif

Présentation​

Shops permet aux joueurs d'acheter et de vendre des objets depuis un menu d'inventaire que vous construisez dans le panneau web de TypeWriter. Une boutique est une entrée Shop Definition : elle contient la liste des objets en vente, leurs prix, la monnaie, les limites, les messages et la disposition du menu. Un joueur l'ouvre avec /tw shop <id> ou depuis une action Open Shop déclenchée par une quête, un PNJ ou un bouton d'un autre menu.

Chaque objet est tarifé de l'une de trois façons : un prix fixe, un prix dynamique qui suit le stock, ou le troc, où l'objet est payé avec d'autres objets plutôt qu'avec de l'argent. Les achats et les ventes passent par Vault, une économie PlaceholderAPI ou un solde de points intégré.

Le menu lui-même est dessiné avec l'extension GUI. Vous placez des marqueurs dans un layout là où les produits apparaissent (SHOP_ITEM), ainsi que des boutons étiquetés pour la pagination, la fermeture et les quantités, et Shops les remplit pour chaque joueur.

Fonctionnalités​

  • Prix fixes, dynamiques et en objets — un prix forfaitaire par unité, un prix qui monte quand le stock baisse, ou une liste d'objets à remettre.
  • Troc — priceMode ITEMS vend un article contre un ou plusieurs objets, avec un prix par défaut commun à toute la boutique et le jeton de lore {item_price}.
  • Trois monnaies — VAULT, PLACEHOLDER (solde lu depuis un placeholder PlaceholderAPI, modifié par des commandes console) et un solde POINTS intégré.
  • Actions de clic et quantités — acheter ou vendre 1, une pile, le maximum, tout, une quantité personnalisée via une boîte de dialogue, ou une quantité fixe comme 10 dans un sous-menu.
  • Stock, limites et réinitialisations — stock par objet, limites par joueur et globales, plafonds d'achat et de vente pour toute la boutique, et réinitialisations selon un cron, un intervalle, un rythme quotidien, hebdomadaire ou mensuel.
  • Taxes et promotions — une taxe globale, des surcharges de taxe par objet, et des réductions en pourcentage limitées dans le temps.
  • Menu dans le panneau — pool de layouts, sous-menu, objet de remplissage, lore des prix et formats par défaut du nom et du lore.
  • Onglet d'un menu partagé — une boutique peut devenir une vue d'un châssis GUI plus vaste via baseMenuId.
  • Commandes d'administration — lister, inspecter, ouvrir, réinitialiser, modifier le stock et lire l'historique des transactions.
  • Annonces Discord — les transactions sont annoncées sous forme d'événement que l'extension Discord relaie vers un webhook.

Installation​

  1. Installez l'extension GUI (version 0.17 ou ultérieure) et TypeWriter sur un serveur Paper ou Folia.
  2. Facultatif, pour la monnaie VAULT : installez Vault et un plugin d'économie qui s'y enregistre.
  3. Facultatif, pour les placeholders dans les titres et le lore, et pour la monnaie PLACEHOLDER : installez PlaceholderAPI.
  4. Téléchargez le JAR de Shops depuis les releases GitHub (le bouton du panneau de synthèse ci-dessus), placez-le dans plugins/Typewriter/extensions/ et redémarrez le serveur.
  5. Dans le panneau web, créez une entrée Shop Artifact et nommez-la shop_artifact. Shops lit et écrit son stock, ses limites et ses points via cette entrée.

Premiers pas​

Construisez une petite boutique d'armes payée avec l'argent de Vault :

  1. Sur une page statique, ajoutez une entrée Shop Artifact nommée shop_artifact.
  2. Ajoutez une entrée Shop Definition. Définissez title sur <gold>Weapons, rows sur 3 et currency sur VAULT.
  3. Dans items, ajoutez un objet. Choisissez une épée en diamant dans item, définissez name sur <aqua>Sword, priceMode sur FIXED, fixedBuyPrice sur 500 et fixedSellPrice sur 100. Laissez primaryAction sur BUY_1 et secondaryAction sur SELL_1.
  4. Dans layoutPool, ajoutez un layout simple avec l'id main, et écrivez main dans mainLayoutId. Ajoutez-y un objet avec buttonPrefix shop_button:, buttonType SHOP_ITEM, x 1, y 1, count 7 et direction right. Cette rangée de marqueurs est l'endroit où les produits apparaissent.
  5. Ajoutez trois autres objets au layout avec buttonPrefix shop_button: et buttonType défini sur PREV_PAGE, NEXT_PAGE et CLOSE, placés sur la dernière ligne. Donnez à chacun un item et un displayName.
  6. Définissez fillerItem sur une vitre teintée grise afin de remplir les emplacements inutilisés.
  7. Publiez, puis exécutez /tw shop admin list en jeu pour lire l'identifiant de la boutique, et ouvrez-la avec /tw shop <id>. Pour l'ouvrir plutôt depuis une quête ou un PNJ, ajoutez une action Open Shop pointant vers la boutique.

Un clic gauche achète une épée, un clic droit en vend une, et Maj + clic gauche ouvre le sous-menu d'achat si vous en avez configuré un.

Objets affichés, objets vendus

Une boutique affiche autant de produits par page qu'elle a d'emplacements de marqueurs SHOP_ITEM, et les boutons de pagination parcourent le reste. S'il n'existe aucun marqueur, le menu s'ouvre sans aucun produit.

Fonctionnement​

À l'ouverture, la boutique vérifie ses criteria d'accès, applique une réinitialisation en attente, puis construit le menu pour ce joueur. Un clic envoie l'action au gestionnaire de transactions, qui vérifie les limites, calcule le prix avec les promotions et la taxe, prélève le paiement, remet l'objet et enregistre le stock, les compteurs de limites et l'historique.

Layout et boutons​

Un menu de boutique est un layout simple du layoutPool de la Shop Definition, sélectionné par mainLayoutId. Les objets du layout portent un buttonPrefix valant shop_button: et un buttonType :

buttonTypeRôle
SHOP_ITEMUn emplacement où un produit est placé. Répétez-le avec count, direction, gap et repeatY. Le préfixe peut rester vide pour ce marqueur.
NEXT_PAGE, PREV_PAGEParcourent les pages de produits.
INFOEnvoie les lignes de infoMessage.
CLOSEFerme le menu.
BACKRetourne au menu précédent, par exemple depuis un sous-menu.
BUY_1, SELL_1Achètent ou vendent une unité. Dans un sous-menu, BUY_1:10 et SELL_1:10 échangent 10 unités ; n'importe quel nombre fonctionne.
BUY_STACK, SELL_STACKÉchangent une pile complète de l'objet.
BUY_MAX, SELL_ALLAchètent autant que possible, ou vendent tout ce qui correspond.
BUY_CUSTOM, SELL_CUSTOMDemandent une quantité au joueur dans une boîte de dialogue.
BUY_SUBMENU, SELL_SUBMENUOuvrent le sous-menu de l'objet.

Les boutons autres que SHOP_ITEM, NEXT_PAGE, PREV_PAGE, INFO, CLOSE et BACK agissent sur l'objet sélectionné par le joueur ; ils ont donc leur place dans le layout du sous-menu. Définissez toujours le buttonPrefix sur shop_button: : le préfixe par défaut appartient à une autre extension et le bouton resterait inerte.

Sous-menu​

Créez un second layout simple dans le pool, placez-y les boutons de quantité et écrivez son id dans subMenuLayoutId. Le titre provient de subMenuTitle, où {item_name} est le name de l'objet. Les objets l'ouvrent avec les actions BUY_SUBMENU et SELL_SUBMENU, qui correspondent au Maj + clic par défaut.

Actions de clic​

Chaque objet possède trois emplacements d'action :

ChampPar défautClic par défaut
primaryActionBUY_1Clic gauche
secondaryActionSELL_1Clic droit
shiftActionBUY_SUBMENUMaj + clic gauche

Les actions possibles sont NONE, BUY_1, SELL_1, BUY_STACK, SELL_STACK, BUY_MAX, SELL_ALL, BUY_SUBMENU, SELL_SUBMENU, BUY_CUSTOM et SELL_CUSTOM. Le interactionConfig commun à toute la boutique décide quel clic déclenche chaque action (acheter 1, vendre 1, acheter une pile, tout vendre, sous-menu, quantité personnalisée, navigation). Chaque type de clic ne peut exécuter qu'une seule action par objet ; avec la configuration par défaut, plusieurs actions associées à un clic gauche se remplacent donc mutuellement : modifiez interactionConfig si vous utilisez plus de trois actions.

buyMaxEnabled désactive BUY_MAX pour un objet.

Boîte de dialogue de quantité​

BUY_CUSTOM et SELL_CUSTOM ouvrent une boîte de dialogue avec un champ de texte. Personnalisez-la avec buyAmountPrompt, sellAmountPrompt, amountConfirmButton, amountInputLabel, amountInputPlaceholder, amountInputWidth et amountInputMaxLength. La réponse doit être un nombre entier positif ; sinon invalidAmountMessage est envoyé. Les vérifications habituelles du prix, des limites et du solde s'exécutent lorsque la quantité est confirmée.

Affichage des objets​

Les lignes de priceLore sont ajoutées à chaque produit, après le lore propre à l'objet et son lore. defaultNameFormat et defaultLoreFormat servent pour les objets sans name ni lore propres. Dans ces champs, ainsi que dans le name et le lore d'un objet, les jetons suivants sont remplacés ; une ligne qui demande un prix inexistant est supprimée.

JetonRemplacé par
{item}Le nom propre de l'objet.
{buy}, {sell}Prix unitaire formaté. Supprimé lorsque l'objet ne peut être ni acheté ni vendu, lorsque le prix est nul, et sur les objets de troc.
{item_price}Le prix en objets, une ligne par objet demandé, par exemple - 12 × Copper Ingot (formulation réglée par itemPriceLineFormat). Supprimé sur les objets qui ne sont pas payés en objets.
{stock}, {stock_max}Stock actuel et maximum.
{currency}Le currencySymbol.

priceFormat met en forme le prix affiché : {amount} est le nombre avec deux décimales et {currency} le symbole.

Prix et économie​

Modes de prix. FIXED utilise fixedBuyPrice et fixedSellPrice. DYNAMIC utilise dynamicPricing : le prix part de price (et sellPrice pour les ventes) lorsque le stock est plein et tend vers max à mesure que le stock baisse, par paliers de step de stockMax, borné par min et max et arrondi à rounding. ITEMS correspond au troc.

Troc. Avec priceMode ITEMS, listez le coût dans l'itemPrice de l'objet, ou une seule fois pour toute la boutique dans defaultItemPrice. Chaque ligne est un objet et un amount par unité achetée. Plusieurs lignes sont toutes requises à la fois, et acheter plusieurs unités multiplie chaque ligne. La liste propre à un article remplace celle de la boutique, elle ne s'y ajoute jamais. Un objet sans prix nulle part est refusé et consigné dans les logs, jamais donné. Le paiement est vérifié sur tout l'inventaire avant que quoi que ce soit ne soit retiré, la place pour l'objet acheté est vérifiée en premier, et les objets de catalogue sont comparés par identité plutôt que par simple matériau. BUY_MAX achète autant d'unités que l'inventaire peut en payer. Un objet de troc ne peut pas être revendu contre de l'argent. Les objets manquants sont signalés par cannotAffordItemsMessage, où {missing} les liste et {amount} est la quantité.

Monnaies.

currencyComportement
VAULTUtilise l'économie enregistrée auprès de Vault. Nécessite le plugin Vault et un fournisseur.
PLACEHOLDERLit le solde depuis balancePlaceholder et le modifie en exécutant addCommand et removeCommand depuis la console, où {player} et {amount} sont remplacés. Les trois doivent être définis. Des nombres comme 1,250.5 et 12.5k sont compris.
POINTSUn solde tenu par Shops dans son artifact. Il commence à 0 et augmente lorsque les joueurs vendent des objets ; la version actuelle n'a aucune commande pour attribuer des points.

Taxes. taxRate est un pourcentage ajouté aux achats et soustrait aux ventes. Avec taxMode PER_ITEM, le taxRateOverride d'un objet (0 ou plus) le remplace pour cet objet ; -1 conserve le taux de la boutique.

Promotions. Une Shop Promotion réduit d'un pourcentage le prix d'achat et la récompense de vente d'une boutique, pour tous les objets ou pour les targetItemIndices listés (position dans items, à partir de 0).

Stock, limites et réinitialisations​

  • dynamicPricing.stockMax définit le stock d'un objet. Il démarre plein, baisse lorsque les joueurs achètent et monte lorsqu'ils vendent. 0 signifie aucun suivi du stock. Avec perPlayer activé, chaque joueur a son propre stock de chaque objet ; une réinitialisation remplit à nouveau le stock de tous. Tant qu'une boutique est ouverte, defaultRefreshTicks (et le refreshTicks d'un objet) la font se redessiner quand le stock affiché change, ce qui permet de voir les achats des autres joueurs. Le guiSlot d'un objet le fixe à un emplacement précis, et sellAllEnabled désactive son action « tout vendre ». Détails dans Shop Definition.
  • playerLimit et globalLimit plafonnent le nombre d'unités d'un objet qu'un joueur, ou tout le monde ensemble, peut acheter par cycle de réinitialisation. globalPlayerLimit, globalBuyLimit et globalSellLimit plafonnent toute la boutique ; 0 signifie illimité. limitReachedMessage est envoyé lorsqu'un plafond est atteint.
  • reset restaure le stock et efface les compteurs de limites. Les politiques sont none, cron (une expression comme 0 0 * * *), interval (secondes), daily, weekly (le jour 1 est le lundi) et monthly. Les heures utilisent le fuseau horaire du serveur. La première vérification d'un cycle a lieu à l'ouverture de la boutique, et une vérification s'exécute aussi chaque minute.
  • criteria restreint l'accès à la boutique et envoie criteriaFailMessage lorsqu'ils ne correspondent pas. Un objet dont les propres criteria ne correspondent pas est affiché comme lockedItem et ne peut pas être acheté.

Commandes​

Sous-commandes de /typewriter, généralement saisi /tw.

CommandeDescription
/tw shop <shop>Ouvre une boutique pour vous-même. Nécessite typewriter.shop.open.
/tw shop adminListe les commandes d'administration. Nécessite typewriter.shop.admin.
/tw shop admin listListe les boutiques chargées avec leur identifiant, nom, nombre d'objets et nombre de pools.
/tw shop admin info <shop>Affiche une définition de boutique et ses objets avec leur index.
/tw shop admin open <shop> [target]Ouvre une boutique pour un joueur.
/tw shop admin refresh [target]Redessine la boutique ouverte d'un joueur.
/tw shop admin close [target]Ferme la boutique ouverte d'un joueur.
/tw shop admin reset <shop>Réinitialise le stock et les limites immédiatement.
/tw shop admin stock <shop> <item> getAffiche le stock de l'objet à cet index.
/tw shop admin stock <shop> <item> set <amount>Définit le stock. Existe aussi avec add et remove.
/tw shop admin history [target]Affiche les 10 dernières transactions d'un joueur depuis le dernier redémarrage.

<shop> est l'identifiant de l'entrée, complété avec la touche Tab. <item> est la position de l'objet dans les items de la boutique, à partir de 0.

Textes modifiables​

Aucun texte affiché en jeu n'est figé dans le code. Trois types de texte peuvent être modifiés sans rien recompiler.

Ce qu'un joueur lit en commerçant est un champ de la Shop Definition : purchaseMessage, sellMessage, cannotAffordMessage, limitReachedMessage, priceLore et les autres décrits plus haut.

Les formulations de prix, les icônes de tendance et les lignes de pool sont des champs de l'entrée à laquelle ils appartiennent. Leur valeur par défaut est le texte que l'extension a toujours affiché.

ChampEntréePar défautUsage
trendUpIconShop Definition<red>▲</red>Le placeholder trend_icon d'un objet dont le prix a monté depuis le dernier achat ou la dernière vente.
trendDownIconShop Definition<green>▼</green>Le même placeholder quand le prix a baissé.
trendStableIconShop Definition<gray>●</gray>Le même placeholder quand le prix n'a pas bougé, ou qu'aucun prix antérieur n'est connu.
itemPriceLineFormatShop Definition- {amount} × {name}Une ligne du jeton de lore {item_price}, pour chaque objet qu'un prix en objets demande. {amount} est la quantité, {name} le nom de l'objet.
unknownItemNameShop Definitionunknown itemLe nom d'un objet de prix dont le nom propre est illisible, dans {item_price} et dans la liste des objets manquants.
missingItemFormatShop Definition{amount} × {name}Un élément de la liste {missing} de cannotAffordItemsMessage. {amount} est la quantité manquante.
missingItemSeparatorShop Definition, Ce qui se place entre deux éléments de la liste {missing}.
defaultItemNameShop DefinitionItemLe {item_name} de subMenuTitle pour un objet qui n'a pas de name.
noPriceTextShop Definition—Affiché à la place d'un nombre là où un prix en objets n'en a pas : les placeholders buy_price et sell_price, et {price} dans le message d'inventaire plein d'un tel objet.
cooldownFormatShop Definition{d}d:{h}h:{m}m:{s}sLe motif du placeholder cooldown quand le placeholder n'en donne pas. {d} jours, {h}, {m}, {s} complétés à 2 chiffres.
limitedLoreShop Pool<yellow>Limited: <red>{limit}La dernière ligne de lore d'un objet limité du pool. {limit} est la quantité disponible.
unlimitedLoreShop Pool<yellow>UnlimitedLa dernière ligne de lore d'un objet du pool qui n'a pas de limite.

Utilisez %typewriter_shop:<shop>:<n>:trend_icon% dans le lore d'un objet pour afficher l'icône. %typewriter_shop:<shop>:<n>:trend% renvoie up, down, stable ou unknown, et ces quatre mots sont fixes parce que les conditions les comparent.

Ce que répondent les commandes /tw shop, commandes /tw shop admin comprises, est un snippet TypeWriter. Ouvrez plugins/Typewriter/snippets.yml, trouvez la clé sous content.shop, changez la valeur et lancez /tw reload. L'extension enregistre tous ses snippets avec leur texte par défaut au démarrage : ils apparaissent donc dans le fichier après le premier démarrage. Gardez les valeurs par défaut et rien ne change.

Les réponses sont en MiniMessage et sont envoyées sans le préfixe Typewriter : la couleur d'une réponse fait donc partie de son texte. Un {name} dans un texte est remplacé par la valeur indiquée dans le tableau ; un placeholder qui n'existe pas reste tel quel, et une valeur n'est jamais réexaminée à la recherche de placeholders. Une valeur issue de vos pages (un nom de boutique, un nom de joueur, un titre d'inventaire) est affichée telle qu'écrite : ses balises ne sont jamais interprétées. Le journal de la console du serveur reste en anglais.

Snippet (sous content.shop.)Par défautPlaceholders
help<gold>Shop commands:</gold> <yellow>/tw shop <id></yellow> to open a shop, <yellow>/tw shop admin</yellow> for operator tools.aucun
unknown_shop_errorUnknown shop: {shop} (texte brut){shop} (ce qui a été saisi)
admin.helpla liste des commandes d'administration, une par ligneaucun
admin.unknown_shop<red>Unknown shop: {shop}{shop}
admin.list_empty<yellow>No shop definitions are currently loaded.aucun
admin.list_header<gold>Loaded shops ({count}):{count}
admin.list_line<white>- {id} | {name} | items={items} | pools={pools}{id}, {name}, {items}, {pools}
admin.opened<green>Opened {shop} for {player}.{shop}, {player}
admin.refreshed<green>Refreshed the shop session for {player}.{player}
admin.closed<green>Closed the shop session for {player}.{player}
admin.reset<green>Reset runtime stock and limits for {shop}.{shop}
admin.history_header<gold>Recent transactions for {player} ({count}):{player}, {count}
admin.history_empty<yellow>No transactions recorded in the current runtime.aucun
admin.history_line<white>{time} | {type} | {shop}[{index}] | amount={amount} | price={price}{time}, {type}, {shop}, {index}, {amount}, {price}
admin.info_title<gold>=== Shop {shop} ==={shop}
admin.info_name<white>Name: {name}{name}
admin.info_inventory_title<white>Title: {title}{title}
admin.info_currency<white>Currency: {currency} | rows={rows}{currency}, {rows}
admin.info_items<white>Items: {items} direct | pools={pools} | access criteria={criteria}{items}, {pools}, {criteria}
admin.info_reset<white>Reset policy: {policy}{policy}
admin.info_item<white>[{index}] {name} | buy={buy} sell={sell} | playerLimit={playerLimit} globalLimit={globalLimit} | item criteria={criteria}{index}, {name}, {buy}, {sell}, {playerLimit}, {globalLimit}, {criteria}
admin.info_item_unnamed<unnamed> (texte brut)aucun ; c'est le {name} d'un objet sans nom
admin.stock_unlimited<yellow>{shop}[{index}] uses unlimited stock.{shop}, {index}
admin.stock_value<green>{shop}[{index}] stock: {stock}/{max}.{shop}, {index}, {stock}, {max}
admin.stock_out_of_range<red>Stock must stay between 0 and {max}.{max}
admin.stock_updated<green>{shop}[{index}] stock set to {stock}/{max}.{shop}, {index}, {stock}, {max}
admin.unknown_item<red>Unknown direct item index {index} in {shop}.{index}, {shop}

unknown_shop_error est une erreur de commande, affichée en rouge par le jeu pendant la saisie : c'est du texte brut, sans MiniMessage.

Permissions​

PermissionAutorise
typewriter.shop.open/tw shop <shop>. Accordée à tout le monde par défaut.
typewriter.shop.adminToutes les commandes /tw shop admin. Réservée aux opérateurs par défaut.

Placeholders​

Placeholders PlaceholderAPI, avec l'expansion typewriter. <shop> est le nom ou l'identifiant de l'entrée de la boutique et <n> la position de l'objet dans items, à partir de 0.

PlaceholderRenvoie
%typewriter_shop:<shop>:name%Nom de l'entrée.
%typewriter_shop:<shop>:entryid%Identifiant de l'entrée.
%typewriter_shop:<shop>:cooldown%Temps restant avant la prochaine réinitialisation, par défaut sous la forme 0d:00h:00m:00s (le champ cooldownFormat de la boutique ; les versions précédentes utilisaient j pour les jours). Ajoutez un format après un tiret bas, par exemple cooldown_{h}h{m}m, en utilisant {d}, {h}, {m} et {s}.
%typewriter_shop:<shop>:<n>:buy_price%Prix d'achat de l'objet ; le noPriceText de la boutique (— par défaut) sur les objets de troc.
%typewriter_shop:<shop>:<n>:sell_price%Prix de vente de l'objet ; le noPriceText de la boutique (— par défaut) sur les objets de troc.
%typewriter_shop:<shop>:<n>:stock%Stock actuel.
%typewriter_shop:<shop>:<n>:stock_max%Stock maximum.
%typewriter_shop:<shop>:<n>:has_promotion%true lorsqu'une promotion s'applique à l'objet.

Intégration​

  • GUI — Shops ouvre ses menus via le service de sessions de GUI ; gui:back, les sons, les châssis étendus et baseMenuId se comportent donc comme dans n'importe quel autre menu. Définissez baseMenuId sur un châssis Open GUI partagé, ajoutez des views, et la boutique devient un onglet : contentX, contentY, contentColumns et contentRows placent les produits dans le châssis.
  • Discord — après chaque achat ou vente, Shops déclenche un ShopTransactionEvent. Lorsque l'extension Discord est installée et que la boutique définit notificationWebhookId, une entrée Shop Notification met en forme l'annonce.
  • Sons — buySound, sellSound et deniedSound sont joués selon le résultat correspondant.

Entrées​

6 entrées, générées depuis la source de l'extension.

Actions1
Artefacts1
Manifestes4

Dépannage​

Le menu s'ouvre mais n'affiche aucun produit. Le layout n'a aucun marqueur SHOP_ITEM, mainLayoutId ne correspond à aucun id de layout dans layoutPool, ou le layout n'est pas un layout simple. Les produits n'apparaissent que sur les emplacements de marqueurs.

Un bouton ne fait rien. Son buttonPrefix n'est pas shop_button:, ou son buttonType est mal orthographié (les types sont en majuscules). Un bouton de pagination ou de fermeture a aussi besoin du préfixe ; seul SHOP_ITEM tolère un préfixe vide.

La boutique affiche « No economy available ». Avec VAULT, Vault ou son fournisseur d'économie est absent. Avec PLACEHOLDER, l'un de balancePlaceholder, addCommand ou removeCommand est vide. Avec un objet de troc, le message apparaît aussi lorsque ni itemPrice ni defaultItemPrice n'est défini, et la console consigne l'identifiant de la boutique et le numéro de l'objet.

Le stock et les limites sont perdus au redémarrage, ou jamais sauvegardés. Il doit exister une entrée Shop Artifact dont l'identifiant ou le nom est shop_artifact.

Un objet ne peut pas être vendu. Son prix de vente est nul (celui des objets de troc l'est toujours), sellEnabled est désactivé, ou le joueur ne possède pas assez d'objets correspondants. Seuls les objets de type et de données identiques comptent.

La console signale qu'un objet ne peut pas être affiché, ou a été déplacé. Un objet avec un guiSlot occupe un marqueur SHOP_ITEM. Quand les objets fixés occupent tous les marqueurs, les autres objets sont placés sur les cases libres de la zone de contenu ; s'il n'y a plus aucune case libre, l'objet n'est pas affiché. Ajoutez des marqueurs SHOP_ITEM ou libérez un emplacement.

Des objets de itemPools apparaissent mais ne peuvent pas être achetés. Seules les entrées de items sont gérées par les actions d'achat et de vente dans cette version ; les objets des pools sont affichés après elles.

Les limites ne se réinitialisent jamais. reset vaut none. Choisissez une politique ou utilisez /tw shop admin reset <shop>.

/tw shop <id> indique que la boutique est inconnue. La commande prend l'identifiant de l'entrée, pas le titre. Utilisez /tw shop admin list.

Extensions associées​

  • GUI — layouts, sessions et mécanisme de marqueurs utilisés par les menus de boutique.
  • Discord — annonce les transactions de boutique sur un webhook.
  • Quest Codex — utilise la même idée de châssis pour les menus de quêtes.