Shops
概要
Shops を使うと、プレイヤーは、TypeWriter の Web パネルで作成したインベントリメニューからアイテムを売買できます。ショップは 1 つの Shop Definition エントリーで、販売するアイテムのリスト、価格、通貨、購入制限、メッセージ、メニューのレイアウトを保持します。プレイヤーは /tw shop <id> で開くか、クエスト、NPC、別のメニューのボタンから発火される Open Shop アクションで開きます。
各アイテムの価格設定は、次の 3 通りのいずれかです。固定価格、在庫に連動する動的価格、そして、お金の代わりに他のアイテムで支払う**物々交換(バーター)**です。購入と売却は、Vault、PlaceholderAPI のエコノミー、または組み込みのポイント残高を通じて行われます。
メニュー自体は GUI エクステンションで描画されます。商品を表示する位置のマーカー(SHOP_ITEM)と、ページ送り、閉じる、数量のためのタグ付きボタンをレイアウトに配置すると、Shops がプレイヤーごとにそれらを埋めます。
機能
- 固定価格、動的価格、アイテム価格 — 1 個あたりの均一価格、在庫が減るほど上がる価格、または引き渡すアイテムのリスト。
- バーター —
priceModeのITEMSは、商品を 1 つまたは複数のアイテムと引き換えに販売します。ショップ全体のデフォルト価格と、ロアのトークン{item_price}があります。 - 3 種類の通貨 —
VAULT、PLACEHOLDER(PlaceholderAPI のプレースホルダーから残高を読み取り、コンソールコマンドで変更)、組み込みのPOINTS残高。 - クリックアクションと数量 — 1 個、1 スタック、最大数、すべて、ダイアログで指定する任意の数量、またはサブメニューでの 10 個などの固定数量を、購入または売却できます。
- 在庫、制限、リセット — アイテムごとの在庫、プレイヤー単位と全体の購入制限、ショップ全体の購入および売却の上限、cron、間隔、毎日、毎週、毎月のスケジュールでのリセット。
- 税とプロモーション — グローバルな税、アイテムごとの税のオーバーライド、期間限定のパーセント割引。
- パネルで作るメニュー — レイアウトプール、サブメニュー、フィラーアイテム、価格のロア、デフォルトの名前とロアの書式。
- 共有メニューのタブ —
baseMenuIdにより、ショップを大きな GUI シャーシのビューにできます。 - 管理コマンド — 一覧表示、確認、オープン、リセット、在庫の編集、取引履歴の読み取り。
- Discord への通知 — 取引は、Discord エクステンションが Webhook に中継するイベントとして通知されます。
インストール
- Paper または Folia サーバーに、GUI エクステンション(バージョン 0.17 以降)と TypeWriter をインストールします。
- 任意、
VAULT通貨用: Vault と、Vault に登録されるエコノミープラグインをインストールします。 - 任意、タイトルとロアのプレースホルダー、および
PLACEHOLDER通貨用: PlaceholderAPI をインストールします。 - GitHub リリース(上のサマリーパネルのボタン)から Shops の JAR をダウンロードし、
plugins/Typewriter/extensions/に配置して、サーバーを再起動します。 - Web パネルで Shop Artifact エントリーを 1 つ作成し、名前を
shop_artifactにします。Shops は、このエントリーを通じて、在庫、購入制限、ポイントの読み書きを行います。
はじめに
Vault のお金で支払う、小さな武器ショップを作成します。
- スタティックページに、
shop_artifactという名前の Shop Artifact エントリーを追加します。 - Shop Definition エントリーを追加します。
titleを<gold>Weapons、rowsを3、currencyをVAULTに設定します。 itemsにアイテムを追加します。itemでダイヤモンドの剣を選び、nameを<aqua>Sword、priceModeをFIXED、fixedBuyPriceを500、fixedSellPriceを100に設定します。primaryActionはBUY_1、secondaryActionはSELL_1のままにします。layoutPoolに、idがmainのsimpleレイアウトを追加し、mainLayoutIdにmainと入力します。そこに、buttonPrefixをshop_button:、buttonTypeをSHOP_ITEM、xを 1、yを 1、countを 7、directionをrightにしたアイテムを追加します。このマーカーの行が、商品が表示される場所です。buttonPrefixをshop_button:にし、buttonTypeをPREV_PAGE、NEXT_PAGE、CLOSEに設定したアイテムを、最下段に 3 つ追加します。それぞれにitemとdisplayNameを設定します。- 使われていないスロットが埋まるよう、
fillerItemを灰色の色付きガラス板に設定します。 - Publish してから、ゲーム内で
/tw shop admin listを実行してショップ ID を確認し、/tw shop <id>で開きます。クエストや NPC から開く場合は、そのショップを指す Open Shop アクションを追加してください。
左クリックで剣を 1 本購入、右クリックで 1 本売却、Shift + 左クリックで、設定している場合は購入サブメニューが開きます。
ショップは、SHOP_ITEM マーカースロットの数だけ、1 ページに商品を表示し、残りはページ送りボタンで移動します。マーカーがない場合、メニューは商品が 1 つもない状態で開きます。
仕組み
ショップは、開かれるとまずアクセスの criteria を確認し、保留中のリセットを適用してから、そのプレイヤー用のメニューを構築します。クリックすると、アクションが取引ハンドラーに送られ、ハンドラーが、購入制限を確認し、プロモーションと税を含めた価格を計算し、支払いを受け取り、アイテムを渡し、在庫、購入制限のカウンター、履歴を記録します。
メニュー
レイアウトとボタン
ショップメニューは、Shop Definition の layoutPool にある simple レイアウトで、mainLayoutId によって選択されます。レイアウト内のアイテムには、shop_button: の buttonPrefix と buttonType を設定します。
buttonType | 役割 |
|---|---|
SHOP_ITEM | 商品が配置されるスロット。count、direction、gap、repeatY で繰り返せます。このマーカーでは、プレフィックスを空のままにしても構いません。 |
NEXT_PAGE, PREV_PAGE | 商品のページを移動します。 |
INFO | infoMessage の行を送信します。 |
CLOSE | メニューを閉じます。 |
BACK | たとえばサブメニューから、前のメニューに戻ります。 |
BUY_1, SELL_1 | 1 個を購入または売却します。サブメニューでは、BUY_1:10 と SELL_1:10 で 10 個を取引でき、任意の数値を指定できます。 |
BUY_STACK, SELL_STACK | アイテムを 1 スタック分取引します。 |
BUY_MAX, SELL_ALL | 可能な限り購入する、または一致するものをすべて売却します。 |
BUY_CUSTOM, SELL_CUSTOM | ダイアログで、プレイヤーに数量を尋ねます。 |
BUY_SUBMENU, SELL_SUBMENU | そのアイテムのサブメニューを開きます。 |
SHOP_ITEM、NEXT_PAGE、PREV_PAGE、INFO、CLOSE、BACK 以外のボタンは、プレイヤーが選択したアイテムに対して作用するため、サブメニューのレイアウトに配置します。buttonPrefix は必ず shop_button: に設定してください。デフォルトのプレフィックスは別のエクステンションのものなので、ボタンが無反応になります。
サブメニュー
プール内に 2 つ目の simple レイアウトを作成し、そこに数量ボタンを配置して、その id を subMenuLayoutId に入力します。タイトルは subMenuTitle から取得され、{item_name} はアイテムの name です。アイテムは、BUY_SUBMENU と SELL_SUBMENU アクション(デフォルトの Shift クリック)でこれを開きます。
クリックアクション
各アイテムには、3 つのアクションスロットがあります。
| フィールド | デフォルト | デフォルトのクリック |
|---|---|---|
primaryAction | BUY_1 | 左クリック |
secondaryAction | SELL_1 | 右クリック |
shiftAction | BUY_SUBMENU | Shift + 左クリック |
指定できるアクションは、NONE、BUY_1、SELL_1、BUY_STACK、SELL_STACK、BUY_MAX、SELL_ALL、BUY_SUBMENU、SELL_SUBMENU、BUY_CUSTOM、SELL_CUSTOM です。どのクリックがどのアクション(1 個購入、1 個売却、スタック購入、すべて売却、サブメニュー、任意の数量、ナビゲーション)を発動させるかは、ショップ全体の interactionConfig で決まります。各クリックタイプは、アイテムごとに 1 つのアクションしか実行できないため、デフォルトの設定では、左クリックに割り当てられた複数のアクションが互いを置き換えます。4 つ以上のアクションを使う場合は、interactionConfig を変更してください。
buyMaxEnabled は、アイテムの BUY_MAX を無効にします。
数量ダイアログ
BUY_CUSTOM と SELL_CUSTOM は、テキストフィールドが 1 つのダイアログを開きます。buyAmountPrompt、sellAmountPrompt、amountConfirmButton、amountInputLabel、amountInputPlaceholder、amountInputWidth、amountInputMaxLength でカスタマイズできます。入力は正の整数でなければならず、そうでない場合は invalidAmountMessage が送信されます。通常の価格、購入制限、残高のチェックは、数量が確定されたときに実行されます。
アイテムの表示
priceLore の行は、各商品に、アイテム自身のロアと、その lore の後ろに追加されます。defaultNameFormat と defaultLoreFormat は、独自の name や lore を持たないアイテムに使用されます。これらのフィールドと、アイテムの name と lore では、次のトークンが置き換えられます。存在しない価格を求める行は削除されます。
| トークン | 置き換え先 |
|---|---|
{item} | アイテム自身の名前。 |
{buy}, {sell} | 書式化された単価。アイテムが購入または売却できない場合、価格がゼロの場合、バーターアイテムの場合は削除されます。 |
{item_price} | アイテムでの価格。要求されるアイテムごとに 1 行で、たとえば - 12 × Copper Ingot のようになります(文言は itemPriceLineFormat で設定)。アイテムで支払わない商品では削除されます。 |
{stock}, {stock_max} | 現在の在庫と最大在庫。 |
{currency} | currencySymbol。 |
priceFormat は、表示される価格の形を決めます。{amount} は小数点以下 2 桁の数値、{currency} は通貨記号です。
価格とエコノミー
価格モード。 FIXED は fixedBuyPrice と fixedSellPrice を使用します。DYNAMIC は dynamicPricing を使用します。価格は、在庫が満タンのとき price(売却では sellPrice)から始まり、在庫が減るにつれて max に向かって stockMax の step 刻みで変化し、min と max で制限され、rounding で丸められます。ITEMS はバーターです。
バーター。 priceMode が ITEMS の場合、コストは、アイテムの itemPrice に、またはショップ全体で 1 回だけ defaultItemPrice に記述します。各行は、購入 1 単位あたりのアイテムと amount です。複数の行はすべて同時に必要で、複数単位を購入すると、すべての行が倍になります。商品自身のリストは、ショップのリストを置き換えるもので、加算されることはありません。どこにも価格がないアイテムは、拒否されてログに記録され、無料で渡されることはありません。支払いは、何かを取り除く前にインベントリ全体で確認され、購入するアイテム用のスペースが先に確認されます。カタログのアイテムは、素材だけでなく同一性で照合されます。BUY_MAX は、インベントリが支払える限りの単位数を購入します。バーターアイテムを、お金で売り戻すことはできません。不足しているアイテムは cannotAffordItemsMessage で通知され、{missing} が不足分の一覧、{amount} が数量です。
通貨。
currency | 動作 |
|---|---|
VAULT | Vault に登録されたエコノミーを使用します。Vault プラグインとプロバイダーが必要です。 |
PLACEHOLDER | balancePlaceholder から残高を読み取り、コンソールから addCommand と removeCommand を実行して変更します。{player} と {amount} は置き換えられます。3 つすべてを設定する必要があります。1,250.5 や 12.5k のような数値も解釈されます。 |
POINTS | Shops がアーティファクトに保持する残高です。0 から始まり、プレイヤーがアイテムを売却すると増えます。このリリースには、ポイントを付与するコマンドはありません。 |
税。 taxRate は、購入に加算され、売却から差し引かれるパーセンテージです。taxMode が PER_ITEM の場合、アイテムの taxRateOverride(0 以上)がそのアイテムに対してこれを置き換えます。-1 はショップの税率を維持します。
プロモーション。 Shop Promotion は、ショップの購入価格と売却報酬を、すべてのアイテム、または列挙した targetItemIndices(items 内の位置、0 から)に対して、パーセンテージで割り引きます。
在庫、制限、リセット
dynamicPricing.stockMaxは、アイテムの在庫を設定します。在庫は満タンから始まり、プレイヤーが購入すると減り、売却すると増えます。0は在庫を追跡しないという意味です。perPlayerを有効にすると、各プレイヤーがアイテムごとに自分専用の在庫を持ち、リセットすると全員の在庫が補充されます。ショップが開いている間は、defaultRefreshTicks(およびアイテムのrefreshTicks)によって、表示中の在庫が変わったときに再描画されるため、他のプレイヤーの購入が見えます。アイテムのguiSlotはそのアイテムを固定スロットに配置し、sellAllEnabledはそのアイテムの「すべて売却」アクションを無効にします。詳細は Shop Definition を参照してください。playerLimitとglobalLimitは、1 つのアイテムを、リセットサイクルごとに、プレイヤー 1 人、または全員合計で購入できる単位数の上限です。globalPlayerLimit、globalBuyLimit、globalSellLimitはショップ全体の上限で、0は無制限です。上限に達するとlimitReachedMessageが送信されます。resetは、在庫を復元し、購入制限のカウンターをクリアします。ポリシーは、none、cron(0 0 * * *のような式)、interval(秒)、daily、weekly(1 日目が月曜日)、monthlyです。時刻にはサーバーのタイムゾーンが使われます。サイクルの最初のチェックは、ショップが開かれたときに行われ、チェックは 1 分ごとにも実行されます。criteriaは、ショップへのアクセスを制限し、一致しない場合はcriteriaFailMessageを送信します。アイテム自身のcriteriaに一致しない場合、そのアイテムはlockedItemとして表示され、購入できません。
コマンド
/typewriter のサブコマンドで、通常は /tw と入力します。
| コマンド | 説明 |
|---|---|
/tw shop <shop> | 自分用にショップを開きます。typewriter.shop.open が必要です。 |
/tw shop admin | 管理コマンドを一覧表示します。typewriter.shop.admin が必要です。 |
/tw shop admin list | 読み込まれているショップを、ID、名前、アイテム数、プール数とともに一覧表示します。 |
/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> <item> get | そのインデックスのアイテムの在庫を表示します。 |
/tw shop admin stock <shop> <item> set <amount> | 在庫を設定します。add と remove も使用できます。 |
/tw shop admin history [target] | 最後の再起動以降の、プレイヤーの直近 10 件の取引を表示します。 |
<shop> はエントリー ID で、Tab キーで補完されます。<item> は、ショップの items 内でのアイテムの位置で、0 から始まります。
編集可能なテキスト
ゲーム内に表示されるテキストで、コードに固定されているものはありません。次の 3 種類のテキストは、何も再ビルドせずに変更できます。
プレイヤーが取引中に読むテキストは、Shop Definition のフィールドです: purchaseMessage、sellMessage、cannotAffordMessage、limitReachedMessage、priceLore、およびこれまでに説明したその他のフィールド。
価格の文言、トレンドアイコン、プールの行は、それぞれが属するエントリーのフィールドです。デフォルトは、エクステンションがこれまで表示してきたテキストです。
| フィールド | エントリー | デフォルト | 用途 |
|---|---|---|---|
trendUpIcon | Shop Definition | <red>▲</red> | 最後の購入または売却以降に価格が上がったアイテムの trend_icon プレースホルダー。 |
trendDownIcon | Shop Definition | <green>▼</green> | 価格が下がったときの同じプレースホルダー。 |
trendStableIcon | Shop Definition | <gray>●</gray> | 価格が変わっていない場合や、以前の価格が不明な場合の同じプレースホルダー。 |
itemPriceLineFormat | Shop Definition | - {amount} × {name} | アイテムでの価格が要求するアイテムごとの、{item_price} ロアトークンの 1 行。{amount} は数量、{name} はアイテム名です。 |
unknownItemName | Shop Definition | unknown item | 固有の名前を読み取れない価格アイテムの名前。{item_price} と不足アイテムのリストで使われます。 |
missingItemFormat | Shop Definition | {amount} × {name} | cannotAffordItemsMessage の {missing} リストの 1 項目。{amount} は不足している数量です。 |
missingItemSeparator | Shop Definition | , | {missing} リストの 2 つの項目の間に入るもの。 |
defaultItemName | Shop Definition | Item | name を持たないアイテムに対する、subMenuTitle の {item_name}。 |
noPriceText | Shop Definition | — | アイテムでの価格に数値がない場所で、数値の代わりに表示されます。buy_price と sell_price のプレースホルダー、およびそのようなアイテムのインベントリ満杯メッセージの {price} です。 |
cooldownFormat | Shop Definition | {d}d:{h}h:{m}m:{s}s | プレースホルダーが書式を指定しない場合の cooldown プレースホルダーのパターン。{d} は日数、{h}、{m}、{s} は 2 桁にゼロ埋めされます。 |
limitedLore | Shop Pool | <yellow>Limited: <red>{limit} | プール内の数量限定アイテムの最後のロア行。{limit} は購入可能な数量です。 |
unlimitedLore | Shop Pool | <yellow>Unlimited | プール内の無制限アイテムの最後のロア行。 |
アイコンを表示するには、アイテムのロアで %typewriter_shop:<shop>:<n>:trend_icon% を使用します。%typewriter_shop:<shop>:<n>:trend% は up、down、stable、unknown のいずれかを返します。条件がこれらと比較するため、この 4 つの単語は固定です。
/tw shop コマンドの返信(/tw shop admin コマンドを含む)は、TypeWriter のスニペットです。plugins/Typewriter/snippets.yml を開き、content.shop 配下のキーを見つけて値を変更し、/tw reload を実行します。エクステンションは起動時にすべてのスニペットをデフォルトのテキストで登録するため、初回起動後にファイルに表示されます。デフォルトのままなら何も変わりません。
返信は MiniMessage で、Typewriter のプレフィックスなしで送信されるため、返信の色はテキストの一部です。テキスト内の {name} は、表に記載された値に置き換えられます。存在しないプレースホルダーはそのまま残り、値の中のプレースホルダーが再度検索されることはありません。ページ由来の値(ショップ名、プレイヤー名、インベントリのタイトル)は書かれたとおりに表示され、タグは解釈されません。サーバーコンソールのログは英語のままです。
スニペット(content.shop. 配下) | デフォルト | プレースホルダー |
|---|---|---|
help | <gold>Shop commands:</gold> <yellow>/tw shop <id></yellow> to open a shop, <yellow>/tw shop admin</yellow> for operator tools. | なし |
unknown_shop_error | Unknown shop: {shop} (プレーンテキスト) | {shop} (入力された内容) |
admin.help | 管理コマンドの一覧(1 行に 1 つ) | なし |
admin.unknown_shop | <red>Unknown shop: {shop} | {shop} |
admin.list_empty | <yellow>No shop definitions are currently loaded. | なし |
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. | なし |
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> (プレーンテキスト) | なし。名前を持たないアイテムの {name} になります |
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 はコマンドエラーで、プレイヤーの入力中にゲームが赤色で表示します。MiniMessage を使わないプレーンテキストです。
パーミッション
| パーミッション | 許可される内容 |
|---|---|
typewriter.shop.open | /tw shop <shop>。デフォルトで全員に付与されます。 |
typewriter.shop.admin | すべての /tw shop admin コマンド。デフォルトではオペレーターのみです。 |
プレースホルダー
typewriter エクスパンションを使う PlaceholderAPI のプレースホルダーです。<shop> はショップのエントリー名または ID、<n> は items 内でのアイテムの位置(0 から)です。
| プレースホルダー | 戻り値 |
|---|---|
%typewriter_shop:<shop>:name% | エントリーの名前。 |
%typewriter_shop:<shop>:entryid% | エントリーの ID。 |
%typewriter_shop:<shop>:cooldown% | 次のリセットまでの時間。デフォルトでは 0d:00h:00m:00s の形式です(ショップの cooldownFormat フィールド。以前のリリースでは日に j を使用していました)。アンダースコアの後に書式を追加できます(例: cooldown_{h}h{m}m)。{d}、{h}、{m}、{s} を使用します。 |
%typewriter_shop:<shop>:<n>:buy_price% | アイテムの購入価格。物々交換アイテムではショップの noPriceText(デフォルトは —)。 |
%typewriter_shop:<shop>:<n>:sell_price% | アイテムの売却価格。物々交換アイテムではショップの noPriceText(デフォルトは —)。 |
%typewriter_shop:<shop>:<n>:stock% | 現在の在庫。 |
%typewriter_shop:<shop>:<n>:stock_max% | 最大在庫。 |
%typewriter_shop:<shop>:<n>:has_promotion% | アイテムにプロモーションが適用されている場合は true。 |
連携
- GUI — Shops は GUI のセッションサービスを通じてメニューを開くため、
gui:back、サウンド、拡張シャーシ、baseMenuIdは、他のメニューと同じように動作します。baseMenuIdを共有の Open GUI シェルに設定し、viewsを追加すると、ショップがタブになります。contentX、contentY、contentColumns、contentRowsで、シェル内の商品の配置を決めます。 - Discord — Shops は、購入または売却のたびに
ShopTransactionEventを発火します。Discord エクステンションがインストールされており、ショップがnotificationWebhookIdを設定している場合は、Shop Notification エントリーが通知を整形します。 - サウンド —
buySound、sellSound、deniedSoundが、それぞれの結果に応じて再生されます。
エントリー
6 件のエントリー(拡張機能のソースから生成)。
アクション1
- Open ShopOpen a shop for a player
アーティファクト1
- Shop ArtifactRuntime storage for shops
マニフェスト4
- Item PoolA weighted pool of items for shops
- Shop CategoryA category within a shop
- Shop DefinitionDefines a shop
- Shop PromotionA shop discount promotion
トラブルシューティング
メニューは開くが、商品が表示されない。 レイアウトに SHOP_ITEM マーカーがない、mainLayoutId が layoutPool 内のレイアウトの id と一致していない、またはレイアウトが simple レイアウトでない、のいずれかです。商品は、マーカースロットにのみ表示されます。
ボタンが何も起こさない。 buttonPrefix が shop_button: でないか、buttonType のスペルが間違っています(タイプは大文字です)。ページ送りボタンや閉じるボタンにもプレフィックスが必要です。プレフィックスが空でも許容されるのは SHOP_ITEM だけです。
ショップに "No economy available" と表示される。 VAULT の場合は、Vault またはそのエコノミープロバイダーがありません。PLACEHOLDER の場合は、balancePlaceholder、addCommand、removeCommand のいずれかが空です。バーターアイテムの場合は、itemPrice も defaultItemPrice も設定されていないときにもこのメッセージが表示され、コンソールにショップ ID とアイテム番号が記録されます。
再起動すると在庫と購入制限が失われる、または保存されない。 ID または名前が shop_artifact の Shop Artifact エントリーが必要です。
アイテムを売却できない。 売却価格がゼロ(バーターアイテムは常にゼロ)、sellEnabled がオフ、またはプレイヤーが一致するアイテムを十分に持っていません。アイテムタイプとデータが同一のアイテムのみがカウントされます。
コンソールに、アイテムを表示できない、または移動されたという警告が出る。 guiSlot を持つアイテムは SHOP_ITEM マーカーを占有します。固定されたアイテムがすべてのマーカーを占有すると、残りのアイテムはコンテンツ領域の空きセルに配置されます。空きセルもなければ、そのアイテムは表示されません。SHOP_ITEM マーカーを追加するか、スロットを空けてください。
itemPools のアイテムが表示されるが、購入できない。 このリリースでは、購入と売却のアクションが処理するのは items のエントリーのみで、プールのアイテムは、それらの後に表示されます。
購入制限がリセットされない。 reset が none です。ポリシーを選択するか、/tw shop admin reset <shop> を使用してください。
/tw shop <id> でショップが不明と表示される。 このコマンドが受け付けるのは、タイトルではなくエントリー ID です。/tw shop admin list を使用してください。
関連エクステンション
- GUI — ショップメニューが使用する、レイアウト、セッション、マーカーの仕組み。
- Discord — ショップの取引を Webhook で通知します。
- Quest Codex — クエストメニューで、同じシャーシの考え方を使用します。