Numerical Storage
Descripción general
Numerical Storage te permite crear almacenes numéricos con nombre para cada jugador: una cuenta bancaria, una reserva de maná, una cartera de tokens, una reserva de cualquier recurso. Describes un almacén una sola vez en una definición, y la extensión guarda un saldo y un nivel por jugador.
Un almacén puede tener niveles, cada uno con una capacidad máxima. Los jugadores depositan y retiran mediante un menú de inventario creado con la extensión GUI. El dinero puede provenir de tu plugin de economía a través de Vault, o de cualquier placeholder y comando de consola que elijas. Se pueden añadir intereses según un calendario, y los almacenes se pueden reiniciar, editar o abrir con comandos.
Los saldos se guardan en un artefacto de TypeWriter y se escriben de forma asíncrona, de modo que un depósito nunca bloquea el hilo del servidor. Los saldos, niveles y capacidad se exponen como placeholders de PlaceholderAPI para scoreboards, hologramas y menús.
Características
- Varios almacenes — crea tantas definiciones como necesites, cada una con su propio nombre, prefijo, niveles y menú.
- Niveles y capacidad — cada nivel tiene un saldo máximo; los jugadores suben de nivel para aumentarlo.
- Requisitos de nivel — desbloquea un nivel con comparaciones de placeholders o facts y, opcionalmente, cobra un coste.
- Intereses — un calendario cron, una tasa global, una tasa por nivel y una tasa por permiso, con un tope por ciclo.
- Vault o comandos — los depósitos y retiros pasan por Vault, o por un placeholder más comandos de consola.
- Transferencias — mueve un saldo entre dos almacenes de forma atómica.
- Botones de menú — cantidad fija, porcentaje, todo, cantidad personalizada (diálogo), submenús, mejora y cerrar.
- Persistencia segura — guardados asíncronos, un bloqueo por artefacto y migración automática de archivos antiguos.
- Modo perfil — saldos opcionales por perfil con MMOProfiles.
- Placeholders y comandos — lee valores en cualquier parte y edítalos desde la consola.
Instalación
- Instala la extensión GUI: Numerical Storage la necesita para sus menús. La extensión GUI se publica con el nombre
GuiAndDialogs. - Instala PlaceholderAPI si quieres usar los placeholders
%typewriter_ns_...%. - Opcional: instala Vault (la extensión está compilada contra VaultUnlocked) y un plugin de economía, para usar el modo de transacción
VAULT. - Opcional: instala MMOProfiles para usar
profileMode. - Coloca el JAR de Numerical Storage en
plugins/Typewriter/extensions/y reinicia el servidor.
La ventana de cantidad personalizada usa los diálogos de Paper, por lo que necesita una versión de Paper que los soporte (Minecraft 1.21.6 o posterior).
Desde la versión 0.9, los artefactos nuevos usan un identificador técnico y la versión 2 del esquema JSON. La primera vez que se lee un archivo antiguo, se copia a la nueva ruta, se guarda en backups/numericalstorage/ y se elimina. Conserva una copia de la carpeta assets/ de TypeWriter antes de actualizar.
Primeros pasos
Crea un banco pagado con tu economía de Vault:
- En el panel web de TypeWriter, abre una página de manifest y añade un artefacto Player Numerical Storage. Deja
artifactIdvacío: TypeWriter lo genera. - Añade una Numerical Storage Definition. Establece
displayName(por ejemploBank),prefixy enlaza el artefacto enartifact. - En
levels, añade el primer nivel con unlimitde1000y luego un segundo con5000. RellenadepositMessageylevelUpMessagesi quieres un texto personalizado. - En
transaction, establecetransactionModeenVAULT. - En
menu.transactionButtons, añade un botón de tipoDEPOSITconamountTypeFIXED, unamountde100y el item que se mostrará. Añade un segundo de tipoWITHDRAW. - Añade una acción Open Numerical Storage Menu. Enlaza la
definition. - En su
layoutPool, añade un layoutsimplecon elidmainy establecemainLayoutIdenmain. En el layout, añade un item conbuttonPrefixestablecido ennumericalstorage_button:ybuttonTypeestablecido enDEPOSIT_FIXED:100. Haz lo mismo conWITHDRAW_FIXED:100,UPGRADE_LEVELyNAV_CLOSE. - Enlaza la acción con un diálogo de NPC o un evento de comando, publica y abre el banco en el juego. También puedes ejecutar
/typewriter ns open <definition>.
Después de cada transacción, el menú se vuelve a abrir para mostrar el nuevo saldo. La extensión busca una entrada Open Numerical Storage Menu enlazada con la misma definición. Sin ella, el menú simplemente se cierra.
Cómo funciona
Menús
El menú es un layout de GUI normal. La acción Open Menu lo abre con el título y el número de filas de la definición (menu.title, menu.rows, de 1 a 6), y tu layoutPool decide dónde va cada item. La extensión convierte un item en un botón funcional cuando el item tiene buttonPrefix establecido en numericalstorage_button: y un buttonType de esta lista:
buttonType | Lo que hace el botón |
|---|---|
DEPOSIT_FIXED | Deposita una cantidad fija. Añade la cantidad tras dos puntos, por ejemplo DEPOSIT_FIXED:100. |
DEPOSIT_PERCENT | Deposita un porcentaje del saldo de origen, por ejemplo DEPOSIT_PERCENT:50. |
DEPOSIT_CUSTOM | Cierra el menú y pide una cantidad en un diálogo. |
DEPOSIT_ALL | Deposita el saldo de origen, hasta la capacidad restante. Necesita un amountPlaceholder: en modo VAULT, el botón intenta depositar toda la capacidad restante y falla si el saldo de la economía es menor. |
DEPOSIT_SUBMENU | Abre un submenú de botones de depósito. El id del submenú va tras los dos puntos. |
WITHDRAW_FIXED, WITHDRAW_PERCENT, WITHDRAW_CUSTOM, WITHDRAW_ALL, WITHDRAW_SUBMENU | Igual que los anteriores, para los retiros. El porcentaje se toma del saldo almacenado. |
TRANSFER_FIXED, TRANSFER_PERCENT, TRANSFER_ALL | Mueve saldo a otra definición. El botón proviene de una entrada transactionButtons de tipo TRANSFER con un transferTarget. |
SUB_MENU | Abre el submenú cuyo id va tras los dos puntos, por ejemplo SUB_MENU:deposit_options. |
UPGRADE_LEVEL | Sube al siguiente nivel, o muestra el item de nivel máximo. |
NAV_CLOSE | Cierra el menú. |
Cuando buttonType lleva una cantidad (DEPOSIT_FIXED:100), la extensión elige la entrada de menu.transactionButtons con el mismo tipo, tipo de cantidad y cantidad, y usa su template como item. Sin cantidad, usa la primera entrada que coincida. Cuando nada coincide, se muestra un item de tinte normal con la etiqueta por defecto.
Los submenús se definen en menu.subMenus, como un mapa de un id a un título, un número de filas, botones de transacción colocados en slots, un botón de volver y un botón de cerrar.
Un botón de transferencia necesita el transferTarget de la otra definición (su id de entrada), y el jugador debe tener espacio en el almacén de destino.
Comandos
Todos los comandos son subcomandos de /typewriter (alias /tw). <definition> es una entrada de definición. El [target] opcional selecciona a otro jugador; sin él, el comando se aplica a quien lo ejecuta.
| Comando | Permiso | Descripción |
|---|---|---|
/typewriter ns open <definition> [target] | typewriter.ns.open | Abre el menú del almacén, a través de su entrada Open Menu. |
/typewriter ns add <definition> <amount> [target] | typewriter.ns.add | Suma al saldo. No se comprueba la capacidad. |
/typewriter ns remove <definition> <amount> [target] | typewriter.ns.remove | Resta del saldo, hasta 0. |
/typewriter ns level <definition> <level> [target] | typewriter.ns.level | Establece el nivel y reinicia el saldo a 0. |
/typewriter ns reset <definition> [target] | typewriter.ns.reset | Reinicia el nivel a 1 y el saldo a 0. |
Los comandos /typewriter numstorage tx ..., upgrade y back_main los usan internamente los botones del menú. No hacen nada para un jugador sin un menú abierto.
Con profileMode activado, add, remove, level y reset cambian el saldo y el nivel del perfil del objetivo, igual que el menú.
Respuestas de los comandos
Las respuestas de add, remove, level, reset y open, y las respuestas de error de abajo, son los campos de adminMessages en la definición. Son MiniMessage. Cada una puede usar <player>, <storage> (el id de la definición) y <prefix>.
| Campo | Placeholder adicional | Por defecto |
|---|---|---|
resetMessage | ninguno | Numerical storage reset for <player>. |
levelSetMessage | <level> | Set numerical storage level to <level> for <player>. |
addMessage | <amount> | Added <amount> to <player>. |
removeMessage | <amount> | Removed <amount> from <player>. |
noMenuMessage | ninguno | El mensaje que se muestra cuando el almacenamiento no tiene una entrada Open Menu. |
invalidAmountMessage | <amount> (el valor escrito) | Invalid amount '<amount>'. Use a positive number. Lo muestran add y remove cuando la cantidad no es un número positivo. |
noArtifactMessage | ninguno | El mensaje que muestran add, remove, level y reset cuando no hay ningún artefacto vinculado a la definición. |
noActiveProfileMessage | ninguno | <player> has no active profile. Lo muestran add, remove, level y reset, y al jugador que pulsa una acción de menú, cuando profileMode está activado y el jugador no tiene ningún perfil de MMOProfiles activo. No se escribe nada. |
Los valores por defecto empiezan con el prefijo de Typewriter. Tres textos no pertenecen a ninguna definición, así que son snippets en snippets.yml: numericalstorage.command.player_only (los comandos de los botones del menú ejecutados por un no jugador) y los textos de placeholders numericalstorage.placeholder.interest_disabled (Disabled), numericalstorage.placeholder.interest_error (Error) y numericalstorage.placeholder.capacity_unlimited (el signo de infinito). Las unidades de tiempo de interest_cooldown son los snippets numericalstorage.duration.days, hours, minutes, seconds (cada uno una plantilla con {value}, {value}j por defecto) y numericalstorage.duration.separator.
Permisos
| Permiso | Concede |
|---|---|
typewriter.ns.open | /typewriter ns open. |
typewriter.ns.add | /typewriter ns add. |
typewriter.ns.remove | /typewriter ns remove. |
typewriter.ns.level | /typewriter ns level. |
typewriter.ns.reset | /typewriter ns reset. |
Permisos en interestRates | Dan a un jugador una tasa de interés específica. Se usa el primer permiso de la lista que tenga el jugador. |
Placeholders
Sustituye <id> por el id de entrada de la definición. Necesitan PlaceholderAPI y se leen desde una caché, por lo que son seguros para usar en scoreboards. Con profileMode activado, balance, level, capacity e interest siguen el perfil con el que juega el jugador, igual que el menú.
| Placeholder | Devuelve |
|---|---|
%typewriter_ns_balance_<id>% | El saldo actual. |
%typewriter_ns_level_<id>% | El nivel actual, empezando en 1. |
%typewriter_ns_capacity_<id>% | La capacidad del nivel actual, o el signo de infinito cuando no hay niveles definidos. |
%typewriter_ns_interest_<id>% | La tasa de interés que se aplica al jugador, en porcentaje. |
%typewriter_ns_interest_cooldown_<id>% | El tiempo hasta el próximo ciclo de intereses programado, o Disabled. |
%typewriter_ns_name_<id>% | El displayName de la definición. |
%typewriter_ns_prefix_<id>% | El prefix de la definición. |
Entradas
4 entradas, generadas a partir del código fuente de la extensión.
Acciones2
- Numericalstorage MenuOpens a Numerical Storage menu
- Numericalstorage Open MenuOpens a Numerical Storage menu (triggerable)
Artefactos1
- Player Numericalstorage ArtifactStores the numericalstorage amount per player
Manifiestos1
- Numericalstorage DefinitionDefines a configurable numerical storage
Solución de problemas
El menú se abre vacío o los botones no hacen nada. Comprueba que cada item tiene buttonPrefix establecido exactamente en numericalstorage_button: y un buttonType válido. Si el prefijo es incorrecto, el item sigue siendo un item normal sin acción. Comprueba también que mainLayoutId coincide con el id de un layout en layoutPool.
El menú se cierra tras cada depósito. El menú se vuelve a abrir mediante una entrada Open Numerical Storage Menu enlazada con la misma definición. Añade una, aunque abras el menú con otra entrada.
"Cannot add ... Would exceed limit". El almacén está en la capacidad del nivel del jugador (levels[].limit). Sube de nivel o aumenta el límite. Sin niveles definidos, no hay límite.
Un depósito en modo INTERNAL falla. El saldo de origen del jugador se lee con amountPlaceholder y debe devolver un número simple. El addCommand se ejecuta desde la consola antes del depósito y debe tener éxito. Usa {player} y {amount} en el comando.
"Economy system is not available." transactionMode es VAULT pero falta Vault o un proveedor de economía. Instala ambos y reinicia.
No se pagan intereses. Los intereses se aplican cuando un jugador se conecta, por los ciclos cron transcurridos desde su último pago (como máximo 100 ciclos). interestEnabled debe estar activado e interestCron rellenado. La primera conexión solo registra la hora de inicio. Un saldo en la capacidad de su nivel no genera nada.
La mejora pide la capacidad como coste. Cuando el siguiente nivel no tiene criteria, el coste de una mejora es el limit del nivel actual, tomado del saldo almacenado. Añade criteria al siguiente nivel para definir un requisito distinto.
Los placeholders muestran el saldo de otro perfil. Con profileMode activado, los placeholders y el botón de mejora leen el saldo y el nivel del perfil seleccionado por el jugador. Sin MMOProfiles leen el saldo propio del jugador. Con MMOProfiles y sin perfil activo (pantalla de selección, tras /mmoprofiles quit) muestran 0, porque el UUID del jugador es el id de su perfil Main y su saldo no debe mostrarse ni acreditarse. Las escrituras se rechazan con noActiveProfileMessage, y el interés de un perfil se liquida al seleccionarlo.
Un placeholder aparece vacío justo después de reiniciar. El almacenamiento se carga en segundo plano al entrar: la primera lectura puede llegar antes de que termine la carga; la siguiente muestra el valor guardado.
El placeholder está vacío. El id del placeholder debe ser el id de entrada de la definición, no su nombre. Ejecuta /papi parse me %typewriter_ns_balance_<id>% para probarlo.
Extensiones relacionadas
- GUI — el motor de menús usado para los layouts y botones.
- MMOProfiles — opcional, lo usa
profileMode.