Shops
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 —
priceModeITEMSvend 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 soldePOINTSinté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
- Installez l'extension GUI (version 0.17 ou ultérieure) et TypeWriter sur un serveur Paper ou Folia.
- Facultatif, pour la monnaie
VAULT: installez Vault et un plugin d'économie qui s'y enregistre. - Facultatif, pour les placeholders dans les titres et le lore, et pour la monnaie
PLACEHOLDER: installez PlaceholderAPI. - 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. - 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 :
- Sur une page statique, ajoutez une entrée Shop Artifact nommée
shop_artifact. - Ajoutez une entrée Shop Definition. Définissez
titlesur<gold>Weapons,rowssur3etcurrencysurVAULT. - Dans
items, ajoutez un objet. Choisissez une épée en diamant dansitem, définisseznamesur<aqua>Sword,priceModesurFIXED,fixedBuyPricesur500etfixedSellPricesur100. LaissezprimaryActionsurBUY_1etsecondaryActionsurSELL_1. - Dans
layoutPool, ajoutez un layoutsimpleavec l'idmain, et écrivezmaindansmainLayoutId. Ajoutez-y un objet avecbuttonPrefixshop_button:,buttonTypeSHOP_ITEM,x1,y1,count7 etdirectionright. Cette rangée de marqueurs est l'endroit où les produits apparaissent. - Ajoutez trois autres objets au layout avec
buttonPrefixshop_button:etbuttonTypedéfini surPREV_PAGE,NEXT_PAGEetCLOSE, placés sur la dernière ligne. Donnez à chacun unitemet undisplayName. - Définissez
fillerItemsur une vitre teintée grise afin de remplir les emplacements inutilisés. - Publiez, puis exécutez
/tw shop admin listen 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.
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.
Menus
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 :
buttonType | Rôle |
|---|---|
SHOP_ITEM | Un 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_PAGE | Parcourent les pages de produits. |
INFO | Envoie les lignes de infoMessage. |
CLOSE | Ferme le menu. |
BACK | Retourne au menu précédent, par exemple depuis un sous-menu. |
BUY_1, SELL_1 | Achè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_ALL | Achètent autant que possible, ou vendent tout ce qui correspond. |
BUY_CUSTOM, SELL_CUSTOM | Demandent une quantité au joueur dans une boîte de dialogue. |
BUY_SUBMENU, SELL_SUBMENU | Ouvrent 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 :
| Champ | Par défaut | Clic par défaut |
|---|---|---|
primaryAction | BUY_1 | Clic gauche |
secondaryAction | SELL_1 | Clic droit |
shiftAction | BUY_SUBMENU | Maj + 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.
| Jeton | Remplacé 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.
currency | Comportement |
|---|---|
VAULT | Utilise l'économie enregistrée auprès de Vault. Nécessite le plugin Vault et un fournisseur. |
PLACEHOLDER | Lit 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. |
POINTS | Un 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.stockMaxdéfinit le stock d'un objet. Il démarre plein, baisse lorsque les joueurs achètent et monte lorsqu'ils vendent.0signifie aucun suivi du stock. AvecperPlayeractivé, 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 lerefreshTicksd'un objet) la font se redessiner quand le stock affiché change, ce qui permet de voir les achats des autres joueurs. LeguiSlotd'un objet le fixe à un emplacement précis, etsellAllEnableddésactive son action « tout vendre ». Détails dans Shop Definition.playerLimitetglobalLimitplafonnent le nombre d'unités d'un objet qu'un joueur, ou tout le monde ensemble, peut acheter par cycle de réinitialisation.globalPlayerLimit,globalBuyLimitetglobalSellLimitplafonnent toute la boutique ;0signifie illimité.limitReachedMessageest envoyé lorsqu'un plafond est atteint.resetrestaure le stock et efface les compteurs de limites. Les politiques sontnone,cron(une expression comme0 0 * * *),interval(secondes),daily,weekly(le jour 1 est le lundi) etmonthly. 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.criteriarestreint l'accès à la boutique et envoiecriteriaFailMessagelorsqu'ils ne correspondent pas. Un objet dont les proprescriteriane correspondent pas est affiché commelockedItemet ne peut pas être acheté.
Commandes
Sous-commandes de /typewriter, généralement saisi /tw.
| Commande | Description |
|---|---|
/tw shop <shop> | Ouvre une boutique pour vous-même. Nécessite typewriter.shop.open. |
/tw shop admin | Liste les commandes d'administration. Nécessite typewriter.shop.admin. |
/tw shop admin list | Liste 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> get | Affiche 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é.
| Champ | Entrée | Par défaut | Usage |
|---|---|---|---|
trendUpIcon | Shop Definition | <red>▲</red> | Le placeholder trend_icon d'un objet dont le prix a monté depuis le dernier achat ou la dernière vente. |
trendDownIcon | Shop Definition | <green>▼</green> | Le même placeholder quand le prix a baissé. |
trendStableIcon | Shop Definition | <gray>●</gray> | Le même placeholder quand le prix n'a pas bougé, ou qu'aucun prix antérieur n'est connu. |
itemPriceLineFormat | Shop 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. |
unknownItemName | Shop Definition | unknown item | Le nom d'un objet de prix dont le nom propre est illisible, dans {item_price} et dans la liste des objets manquants. |
missingItemFormat | Shop Definition | {amount} × {name} | Un élément de la liste {missing} de cannotAffordItemsMessage. {amount} est la quantité manquante. |
missingItemSeparator | Shop Definition | , | Ce qui se place entre deux éléments de la liste {missing}. |
defaultItemName | Shop Definition | Item | Le {item_name} de subMenuTitle pour un objet qui n'a pas de name. |
noPriceText | Shop 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. |
cooldownFormat | Shop Definition | {d}d:{h}h:{m}m:{s}s | Le motif du placeholder cooldown quand le placeholder n'en donne pas. {d} jours, {h}, {m}, {s} complétés à 2 chiffres. |
limitedLore | Shop Pool | <yellow>Limited: <red>{limit} | La dernière ligne de lore d'un objet limité du pool. {limit} est la quantité disponible. |
unlimitedLore | Shop Pool | <yellow>Unlimited | La 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éfaut | Placeholders |
|---|---|---|
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_error | Unknown shop: {shop} (texte brut) | {shop} (ce qui a été saisi) |
admin.help | la liste des commandes d'administration, une par ligne | aucun |
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
| Permission | Autorise |
|---|---|
typewriter.shop.open | /tw shop <shop>. Accordée à tout le monde par défaut. |
typewriter.shop.admin | Toutes 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.
| Placeholder | Renvoie |
|---|---|
%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 etbaseMenuIdse comportent donc comme dans n'importe quel autre menu. DéfinissezbaseMenuIdsur un châssis Open GUI partagé, ajoutez desviews, et la boutique devient un onglet :contentX,contentY,contentColumnsetcontentRowsplacent 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éfinitnotificationWebhookId, une entrée Shop Notification met en forme l'annonce. - Sons —
buySound,sellSoundetdeniedSoundsont joués selon le résultat correspondant.
Entrées
6 entrées, générées depuis la source de l'extension.
Actions1
- Open ShopOpen a shop for a player
Artefacts1
- Shop ArtifactRuntime storage for shops
Manifestes4
- Item PoolA weighted pool of items for shops
- Shop CategoryA category within a shop
- Shop DefinitionDefines a shop
- Shop PromotionA shop discount promotion
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.