Shops
Descripción general
Shops permite a los jugadores comprar y vender objetos desde un menú de inventario que construyes en el panel web de TypeWriter. Una tienda es una única entrada Shop Definition: contiene la lista de objetos a la venta, sus precios, la moneda, los límites, los mensajes y el layout del menú. Un jugador la abre con /tw shop <id> o desde una acción Open Shop disparada por una misión, un NPC o un botón de otro menú.
Cada objeto tiene un precio de una de estas tres formas: un precio fijo, un precio dinámico que sigue las existencias o trueque, en el que el objeto se paga con otros objetos en lugar de con dinero. Las compras y las ventas pasan por Vault, una economía de PlaceholderAPI o un saldo de puntos integrado.
El propio menú se dibuja con la extensión GUI. Colocas marcadores en un layout donde aparecen los productos (SHOP_ITEM) y botones etiquetados para paginar, cerrar y elegir cantidades, y Shops los rellena para cada jugador.
Características
- Precios fijos, dinámicos y en objetos: un precio único por unidad, un precio que sube a medida que bajan las existencias o una lista de objetos que entregar.
- Trueque:
priceModeITEMSvende un artículo a cambio de uno o varios objetos, con un precio por defecto para toda la tienda y el token de lore{item_price}. - Tres monedas:
VAULT,PLACEHOLDER(saldo leído de un placeholder de PlaceholderAPI y modificado con comandos de consola) y un saldoPOINTSintegrado. - Acciones de clic y cantidades: compra o vende 1, una pila, el máximo, todo, una cantidad personalizada desde un diálogo o una cantidad fija como 10 en un submenú.
- Existencias, límites y reinicios: existencias por objeto, límites por jugador y globales, topes de compra y venta para toda la tienda, y reinicios con un calendario cron, por intervalo, diario, semanal o mensual.
- Impuestos y promociones: un impuesto global, sobrescrituras de impuesto por objeto y descuentos porcentuales temporizados.
- Menú en el panel: conjunto de layouts, submenú, objeto de relleno, lore de precios y formatos de nombre y lore por defecto.
- Pestaña de un menú compartido: una tienda puede convertirse en una vista de un chasis de GUI mayor mediante
baseMenuId. - Comandos de administración: listar, inspeccionar, abrir, reiniciar, editar existencias y consultar el historial de transacciones.
- Anuncios en Discord: las transacciones se anuncian como un evento que la extensión Discord retransmite a un webhook.
Instalación
- Instala la extensión GUI (versión 0.17 o posterior) y TypeWriter en un servidor Paper o Folia.
- Opcional, para la moneda
VAULT: instala Vault y un plugin de economía que se registre en él. - Opcional, para los placeholders en títulos y lore, y para la moneda
PLACEHOLDER: instala PlaceholderAPI. - Descarga el JAR de Shops desde las releases de GitHub (el botón del panel de resumen de arriba), colócalo en
plugins/Typewriter/extensions/y reinicia el servidor. - En el panel web, crea una entrada Shop Artifact y llámala
shop_artifact. Shops lee y escribe sus existencias, límites y puntos a través de esa entrada.
Primeros pasos
Construye una pequeña tienda de armas pagada con dinero de Vault:
- En una página estática, añade una entrada Shop Artifact llamada
shop_artifact. - Añade una entrada Shop Definition. Establece
titleen<gold>Weapons,rowsen3ycurrencyenVAULT. - En
items, añade un objeto. Elige una espada de diamante enitem, establecenameen<aqua>Sword,priceModeenFIXED,fixedBuyPriceen500yfixedSellPriceen100. DejaprimaryActionenBUY_1ysecondaryActionenSELL_1. - En
layoutPool, añade un layoutsimplecon elidmainy escribemainenmainLayoutId. Añade un objeto conbuttonPrefixshop_button:,buttonTypeSHOP_ITEM,x1,y1,count7 ydirectionright. Esta fila de marcadores es donde aparecen los productos. - Añade al layout tres objetos más con
buttonPrefixshop_button:ybuttonTypeestablecido enPREV_PAGE,NEXT_PAGEyCLOSE, colocados en la fila inferior. Dale a cada uno unitemy undisplayName. - Establece
fillerItemen un panel de cristal tintado gris para que se rellenen las ranuras sin usar. - Publica y ejecuta
/tw shop admin listen el juego para leer el id de la tienda, y ábrela con/tw shop <id>. Para abrirla desde una misión o un NPC, añade una acción Open Shop que apunte a la tienda.
El clic izquierdo compra una espada, el clic derecho vende una, y Shift + clic izquierdo abre el submenú de compra si has configurado uno.
Una tienda muestra tantos productos por página como ranuras marcador SHOP_ITEM tenga, y los botones de paginación recorren el resto. Si no existe ningún marcador, el menú se abre sin ningún producto.
Cómo funciona
Al abrirse, la tienda comprueba sus criteria de acceso, aplica un reinicio pendiente y después construye el menú para ese jugador. Un clic envía la acción al gestor de transacciones, que comprueba los límites, calcula el precio con las promociones y el impuesto, cobra el pago, entrega el objeto y registra las existencias, los contadores de límites y el historial.
Menús
Layout y botones
Un menú de tienda es un layout simple en el layoutPool de la Shop Definition, seleccionado con mainLayoutId. Los objetos del layout llevan un buttonPrefix de shop_button: y un buttonType:
buttonType | Función |
|---|---|
SHOP_ITEM | Una ranura donde se coloca un producto. Repítela con count, direction, gap y repeatY. El prefijo puede dejarse vacío para este marcador. |
NEXT_PAGE, PREV_PAGE | Recorren las páginas de productos. |
INFO | Envía las líneas de infoMessage. |
CLOSE | Cierra el menú. |
BACK | Vuelve al menú anterior, por ejemplo desde un submenú. |
BUY_1, SELL_1 | Compran o venden una unidad. En un submenú, BUY_1:10 y SELL_1:10 comercian con 10 unidades; vale cualquier número. |
BUY_STACK, SELL_STACK | Comercian con una pila completa del objeto. |
BUY_MAX, SELL_ALL | Compran tantas unidades como sea posible o venden todo lo que coincida. |
BUY_CUSTOM, SELL_CUSTOM | Piden al jugador una cantidad en un diálogo. |
BUY_SUBMENU, SELL_SUBMENU | Abren el submenú del objeto. |
Los botones distintos de SHOP_ITEM, NEXT_PAGE, PREV_PAGE, INFO, CLOSE y BACK actúan sobre el objeto que el jugador ha seleccionado, por lo que pertenecen al layout del submenú. Establece siempre el buttonPrefix en shop_button:: el prefijo por defecto pertenece a otra extensión y el botón quedaría inerte.
Submenú
Crea un segundo layout simple en el conjunto, coloca en él los botones de cantidad y escribe su id en subMenuLayoutId. El título procede de subMenuTitle, donde {item_name} es el name del objeto. Los objetos lo abren con las acciones BUY_SUBMENU y SELL_SUBMENU, que son el Shift + clic por defecto.
Acciones de clic
Cada objeto tiene tres ranuras de acción:
| Campo | Valor por defecto | Clic por defecto |
|---|---|---|
primaryAction | BUY_1 | Clic izquierdo |
secondaryAction | SELL_1 | Clic derecho |
shiftAction | BUY_SUBMENU | Shift + clic izquierdo |
Las acciones posibles son NONE, BUY_1, SELL_1, BUY_STACK, SELL_STACK, BUY_MAX, SELL_ALL, BUY_SUBMENU, SELL_SUBMENU, BUY_CUSTOM y SELL_CUSTOM. El interactionConfig de toda la tienda decide qué clic activa cada acción (comprar 1, vender 1, comprar pila, vender todo, submenú, cantidad personalizada, navegación). Cada tipo de clic solo puede ejecutar una acción por objeto, de modo que, con la configuración por defecto, varias acciones asignadas a un clic izquierdo se sustituyen entre sí: cambia interactionConfig si usas más de tres acciones.
buyMaxEnabled desactiva BUY_MAX para un objeto.
Diálogo de cantidad
BUY_CUSTOM y SELL_CUSTOM abren un diálogo con un campo de texto. Personalízalo con buyAmountPrompt, sellAmountPrompt, amountConfirmButton, amountInputLabel, amountInputPlaceholder, amountInputWidth y amountInputMaxLength. La respuesta debe ser un número entero positivo; de lo contrario se envía invalidAmountMessage. Las comprobaciones normales de precio, límite y saldo se ejecutan cuando se confirma la cantidad.
Visualización de los objetos
Las líneas de priceLore se añaden a cada producto, después del lore propio del objeto y de su lore. defaultNameFormat y defaultLoreFormat se aplican a los objetos que no tienen name o lore propios. En estos campos y en el name y el lore de un objeto se sustituyen los siguientes tokens; una línea que pide un precio que no existe se descarta.
| Token | Se sustituye por |
|---|---|
{item} | El nombre propio del objeto. |
{buy}, {sell} | Precio unitario formateado. Se descarta cuando el objeto no se puede comprar o vender, cuando el precio es cero y en los objetos de trueque. |
{item_price} | El precio en objetos, una línea por cada objeto solicitado, como - 12 × Copper Ingot (el texto se define con itemPriceLineFormat). Se descarta en los objetos que no se pagan con objetos. |
{stock}, {stock_max} | Existencias actuales y máximas. |
{currency} | El currencySymbol. |
priceFormat da forma al precio mostrado: {amount} es el número con dos decimales y {currency} el símbolo.
Precios y economía
Modos de precio. FIXED usa fixedBuyPrice y fixedSellPrice. DYNAMIC usa dynamicPricing: el precio empieza en price (y sellPrice para las ventas) cuando las existencias están llenas y se desplaza hacia max a medida que bajan, en pasos de step de stockMax, limitado por min y max y redondeado a rounding. ITEMS es el trueque.
Trueque. Con priceMode ITEMS, enumera el coste en el itemPrice del objeto, o una sola vez para toda la tienda en defaultItemPrice. Cada línea es un objeto y un amount por unidad comprada. Todas las líneas son necesarias a la vez, y comprar varias unidades multiplica cada línea. La lista propia de un artículo sustituye a la de la tienda; nunca se suma a ella. Un objeto sin precio en ningún sitio se rechaza y se registra, nunca se regala. El pago se comprueba sobre todo el inventario antes de retirar nada, primero se comprueba que haya espacio para el objeto comprado, y los objetos del catálogo se identifican por su identidad y no solo por el material. BUY_MAX compra tantas unidades como pueda pagar el inventario. Un objeto de trueque no se puede revender por dinero. Los objetos que faltan se comunican con cannotAffordItemsMessage, donde {missing} los enumera y {amount} es la cantidad.
Monedas.
currency | Comportamiento |
|---|---|
VAULT | Usa la economía registrada en Vault. Necesita el plugin Vault y un proveedor. |
PLACEHOLDER | Lee el saldo de balancePlaceholder y lo modifica ejecutando addCommand y removeCommand desde la consola, donde se sustituyen {player} y {amount}. Deben establecerse los tres. Se entienden números como 1,250.5 y 12.5k. |
POINTS | Un saldo que Shops mantiene en su artefacto. Empieza en 0 y crece cuando los jugadores venden objetos; la versión publicada no tiene ningún comando para conceder puntos. |
Impuestos. taxRate es un porcentaje que se añade a las compras y se resta de las ventas. Con taxMode PER_ITEM, el taxRateOverride de un objeto (0 o más) lo sustituye para ese objeto; -1 mantiene el porcentaje de la tienda.
Promociones. Una Shop Promotion aplica un descuento porcentual al precio de compra y a la recompensa de venta de una tienda, para todos los objetos o para los targetItemIndices indicados (posición en items, desde 0).
Existencias, límites y reinicios
dynamicPricing.stockMaxestablece las existencias de un objeto. Empiezan llenas, bajan cuando los jugadores compran y suben cuando venden.0significa que no se hace seguimiento de existencias. ConperPlayeractivado, cada jugador tiene sus propias existencias de cada objeto; un reinicio rellena las de todos. Mientras una tienda está abierta,defaultRefreshTicks(y elrefreshTicksde un objeto) hacen que se redibuje cuando cambian las existencias mostradas, de modo que se ven las compras de otros jugadores. ElguiSlotde un objeto lo fija en una casilla concreta, ysellAllEnableddesactiva su acción de vender todo. Detalles en Shop Definition.playerLimityglobalLimitlimitan cuántas unidades de un objeto puede comprar un jugador, o todos juntos, por ciclo de reinicio.globalPlayerLimit,globalBuyLimityglobalSellLimitlimitan toda la tienda;0significa ilimitado.limitReachedMessagese envía cuando se alcanza un tope.resetrestablece las existencias y borra los contadores de límites. Las políticas sonnone,cron(una expresión como0 0 * * *),interval(segundos),daily,weekly(el día 1 es el lunes) ymonthly. Las horas usan la zona horaria del servidor. La primera comprobación de un ciclo se produce cuando se abre la tienda, y también se ejecuta una comprobación cada minuto.criteriarestringe el acceso a la tienda y envíacriteriaFailMessagecuando no se cumplen. Un objeto cuyos propioscriteriano se cumplen se muestra comolockedItemy no se puede comprar.
Comandos
Subcomandos de /typewriter, que normalmente se escribe como /tw.
| Comando | Descripción |
|---|---|
/tw shop <shop> | Abre una tienda para ti. Requiere typewriter.shop.open. |
/tw shop admin | Lista los comandos de administración. Requiere typewriter.shop.admin. |
/tw shop admin list | Lista las tiendas cargadas con su id, nombre, número de objetos y número de conjuntos. |
/tw shop admin info <shop> | Muestra la definición de una tienda y sus objetos con su índice. |
/tw shop admin open <shop> [target] | Abre una tienda para un jugador. |
/tw shop admin refresh [target] | Vuelve a dibujar la tienda abierta de un jugador. |
/tw shop admin close [target] | Cierra la tienda abierta de un jugador. |
/tw shop admin reset <shop> | Restablece ahora las existencias y los límites. |
/tw shop admin stock <shop> <item> get | Muestra las existencias del objeto en ese índice. |
/tw shop admin stock <shop> <item> set <amount> | Establece las existencias. También add y remove. |
/tw shop admin history [target] | Muestra las últimas 10 transacciones de un jugador desde el último reinicio. |
<shop> es el id de la entrada, que se completa con la tecla Tab. <item> es la posición del objeto en los items de la tienda, empezando en 0.
Textos editables
Ningún texto que se muestra en el juego está fijado en el código. Tres tipos de texto se pueden cambiar sin recompilar nada.
Lo que lee un jugador al comerciar es un campo de la Shop Definition: purchaseMessage, sellMessage, cannotAffordMessage, limitReachedMessage, priceLore y los demás descritos arriba.
Los textos de precio, los iconos de tendencia y las líneas de pool son campos de la entrada a la que pertenecen. Su valor por defecto es el texto que la extensión siempre mostró.
| Campo | Entrada | Por defecto | Uso |
|---|---|---|---|
trendUpIcon | Shop Definition | <red>▲</red> | El placeholder trend_icon de un objeto cuyo precio subió desde la última compra o venta. |
trendDownIcon | Shop Definition | <green>▼</green> | El mismo placeholder cuando el precio bajó. |
trendStableIcon | Shop Definition | <gray>●</gray> | El mismo placeholder cuando el precio no cambió, o cuando no se conoce un precio anterior. |
itemPriceLineFormat | Shop Definition | - {amount} × {name} | Una línea del token de lore {item_price}, por cada objeto que pide un precio en objetos. {amount} es la cantidad y {name} el nombre del objeto. |
unknownItemName | Shop Definition | unknown item | El nombre de un objeto de precio cuyo nombre propio no se puede leer, en {item_price} y en la lista de objetos que faltan. |
missingItemFormat | Shop Definition | {amount} × {name} | Un elemento de la lista {missing} de cannotAffordItemsMessage. {amount} es la cantidad que falta. |
missingItemSeparator | Shop Definition | , | Lo que va entre dos elementos de la lista {missing}. |
defaultItemName | Shop Definition | Item | El {item_name} de subMenuTitle para un objeto que no tiene name. |
noPriceText | Shop Definition | — | Se muestra en lugar de un número donde un precio en objetos no lo tiene: los placeholders buy_price y sell_price, y {price} en el mensaje de inventario lleno de un objeto así. |
cooldownFormat | Shop Definition | {d}d:{h}h:{m}m:{s}s | El patrón del placeholder cooldown cuando el placeholder no indica ninguno. {d} días, {h}, {m}, {s} rellenados a 2 dígitos. |
limitedLore | Shop Pool | <yellow>Limited: <red>{limit} | La última línea de lore de un objeto limitado del pool. {limit} es la cantidad disponible. |
unlimitedLore | Shop Pool | <yellow>Unlimited | La última línea de lore de un objeto del pool sin límite. |
Usa %typewriter_shop:<shop>:<n>:trend_icon% en el lore de un objeto para mostrar el icono. %typewriter_shop:<shop>:<n>:trend% devuelve up, down, stable o unknown, y estas cuatro palabras son fijas porque las condiciones las comparan.
Lo que responden los comandos /tw shop, incluidos los comandos /tw shop admin, es un snippet de TypeWriter. Abre plugins/Typewriter/snippets.yml, busca la clave bajo content.shop, cambia el valor y ejecuta /tw reload. La extensión registra todos sus snippets con su texto por defecto al iniciarse, así que aparecen en el archivo tras el primer arranque. Si mantienes los valores por defecto, nada cambia.
Las respuestas son MiniMessage y se envían sin el prefijo de Typewriter, así que el color de una respuesta forma parte de su texto. Un {name} en un texto se sustituye por el valor indicado en la tabla; un placeholder que no existe se queda tal cual, y un valor nunca se vuelve a examinar en busca de placeholders. Un valor que viene de tus páginas (el nombre de una tienda, el nombre de un jugador, el título de un inventario) se muestra tal como está escrito: sus etiquetas nunca se interpretan. El registro de la consola del servidor sigue en inglés.
Snippet (bajo content.shop.) | Por defecto | Placeholders |
|---|---|---|
help | <gold>Shop commands:</gold> <yellow>/tw shop <id></yellow> to open a shop, <yellow>/tw shop admin</yellow> for operator tools. | ninguno |
unknown_shop_error | Unknown shop: {shop} (texto sin formato) | {shop} (lo que se escribió) |
admin.help | la lista de comandos de administración, uno por línea | ninguno |
admin.unknown_shop | <red>Unknown shop: {shop} | {shop} |
admin.list_empty | <yellow>No shop definitions are currently loaded. | ninguno |
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. | ninguno |
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> (texto sin formato) | ninguno; es el {name} de un objeto sin nombre |
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 es un error de comando, que el juego muestra en rojo mientras el jugador escribe: es texto sin formato, sin MiniMessage.
Permisos
| Permiso | Concede |
|---|---|
typewriter.shop.open | /tw shop <shop>. Concedido a todos por defecto. |
typewriter.shop.admin | Todos los comandos /tw shop admin. Solo para operadores por defecto. |
Placeholders
Placeholders de PlaceholderAPI, con la expansión typewriter. <shop> es el nombre o el id de la entrada de la tienda y <n> la posición del objeto en items, desde 0.
| Placeholder | Devuelve |
|---|---|
%typewriter_shop:<shop>:name% | Nombre de la entrada. |
%typewriter_shop:<shop>:entryid% | Id de la entrada. |
%typewriter_shop:<shop>:cooldown% | Tiempo hasta el próximo reinicio, por defecto con el formato 0d:00h:00m:00s (el campo cooldownFormat de la tienda; las versiones anteriores usaban j para los días). Añade un formato tras un guion bajo, por ejemplo cooldown_{h}h{m}m, usando {d}, {h}, {m} y {s}. |
%typewriter_shop:<shop>:<n>:buy_price% | Precio de compra del objeto; el noPriceText de la tienda (— por defecto) en los objetos de trueque. |
%typewriter_shop:<shop>:<n>:sell_price% | Precio de venta del objeto; el noPriceText de la tienda (— por defecto) en los objetos de trueque. |
%typewriter_shop:<shop>:<n>:stock% | Existencias actuales. |
%typewriter_shop:<shop>:<n>:stock_max% | Existencias máximas. |
%typewriter_shop:<shop>:<n>:has_promotion% | true cuando se aplica una promoción al objeto. |
Integración
- GUI: Shops abre sus menús a través del servicio de sesiones de GUI, por lo que
gui:back, los sonidos, los chasis extendidos ybaseMenuIdse comportan como en cualquier otro menú. EstablecebaseMenuIden una base compartida Open GUI, añadeviewsy la tienda se convierte en una pestaña:contentX,contentY,contentColumnsycontentRowscolocan los productos dentro de la base. - Discord: tras cada compra o venta, Shops dispara un
ShopTransactionEvent. Cuando la extensión Discord está instalada y la tienda definenotificationWebhookId, una entrada Shop Notification da formato al anuncio. - Sonidos:
buySound,sellSoundydeniedSoundse reproducen según el resultado correspondiente.
Entradas
6 entradas, generadas a partir del código fuente de la extensión.
Acciones1
- Open ShopOpen a shop for a player
Artefactos1
- Shop ArtifactRuntime storage for shops
Manifiestos4
- Item PoolA weighted pool of items for shops
- Shop CategoryA category within a shop
- Shop DefinitionDefines a shop
- Shop PromotionA shop discount promotion
Resolución de problemas
El menú se abre pero no muestra ningún producto. El layout no tiene ningún marcador SHOP_ITEM, mainLayoutId no coincide con el id de ningún layout de layoutPool, o el layout no es un layout simple. Los productos solo aparecen en las ranuras marcador.
Un botón no hace nada. Su buttonPrefix no es shop_button:, o su buttonType está mal escrito (los tipos van en mayúsculas). Un botón de paginación o de cierre también necesita el prefijo; solo SHOP_ITEM tolera un prefijo vacío.
La tienda dice "No economy available". Con VAULT, falta Vault o su proveedor de economía. Con PLACEHOLDER, uno de balancePlaceholder, addCommand o removeCommand está vacío. Con un objeto de trueque, el mensaje también aparece cuando no se ha definido ni itemPrice ni defaultItemPrice, y la consola registra el id de la tienda y el número del objeto.
Las existencias y los límites se pierden al reiniciar, o nunca se guardan. Debe existir una entrada Shop Artifact cuyo id o nombre sea shop_artifact.
No se puede vender un objeto. Su precio de venta es cero (los objetos de trueque siempre lo tienen), sellEnabled está desactivado, o el jugador no tiene suficientes objetos que coincidan. Solo cuentan los objetos con un tipo de objeto y datos idénticos.
La consola avisa de que un artículo no se puede mostrar o se ha movido. Un objeto con guiSlot ocupa un marcador SHOP_ITEM. Cuando los objetos fijados ocupan todos los marcadores, los demás objetos se colocan en las casillas libres de la zona de contenido; si no queda ninguna casilla libre, el objeto no se muestra. Añade marcadores SHOP_ITEM o libera una casilla.
Los objetos de itemPools aparecen pero no se pueden comprar. En esta versión, las acciones de compra y venta solo gestionan las entradas de items; los objetos de los conjuntos se muestran después de ellas.
Los límites nunca se reinician. reset es none. Elige una política o usa /tw shop admin reset <shop>.
/tw shop <id> dice que la tienda es desconocida. El comando toma el id de la entrada, no el título. Usa /tw shop admin list.
Extensiones relacionadas
- GUI: layouts, sesiones y el mecanismo de marcadores que usan los menús de tienda.
- Discord: anuncia las transacciones de la tienda en un webhook.
- Quest Codex: usa la misma idea de chasis para los menús de misiones.