Numerical Storage
Обзор
Numerical Storage позволяет создавать для каждого игрока именованные числовые хранилища: банковский счёт, запас маны, кошелёк с жетонами, резерв любого ресурса. Вы описываете хранилище один раз в определении (definition), а расширение сохраняет по одному балансу и одному уровню на игрока.
У хранилища могут быть уровни, у каждого из которых есть максимальная вместимость. Игроки вносят и снимают средства через меню-инвентарь, построенное на расширении GUI. Деньги могут поступать из вашего плагина экономики через Vault либо из любого выбранного вами плейсхолдера и консольной команды. Проценты можно начислять по расписанию, а хранилища можно сбрасывать, редактировать или открывать командами.
Балансы сохраняются в артефакте TypeWriter и записываются асинхронно, поэтому внесение средств никогда не блокирует серверный поток. Балансы, уровни и вместимость доступны как плейсхолдеры PlaceholderAPI для скорбордов, голограмм и меню.
Возможности
- Несколько хранилищ — создавайте сколько угодно определений, у каждого своё имя, префикс, уровни и меню.
- Уровни и вместимость — у каждого уровня есть максимальный баланс; игроки повышают уровень, чтобы увеличить его.
- Требования к уровням — открывайте уровень по сравнению плейсхолдеров или фактов и при желании списывайте стоимость.
- Проценты — расписание cron, глобальная ставка, ставка для каждого уровня и ставка для каждого права, с ограничением на цикл.
- Vault или команды — внесение и снятие проходят через Vault либо через плейсхолдер и консольные команды.
- Переводы — атомарный перенос баланса между двумя хранилищами.
- Кнопки меню — фиксированная сумма, процент, всё, произвольная сумма (диалог), подменю, повышение уровня и закрытие.
- Надёжное сохранение — асинхронные сохранения, одна блокировка на артефакт и автоматическая миграция старых файлов.
- Режим профилей — необязательные балансы для каждого профиля через MMOProfiles.
- Плейсхолдеры и команды — читайте значения где угодно и редактируйте их из консоли.
Установка
- Установите расширение GUI: Numerical Storage нужен он для меню. Расширение GUI публикуется под названием
GuiAndDialogs. - Установите PlaceholderAPI, если хотите использовать плейсхолдеры
%typewriter_ns_...%. - По желанию: установите Vault (расширение собрано под VaultUnlocked) и плагин экономики, чтобы использовать режим транзакций
VAULT. - По желанию: установите MMOProfiles, чтобы использовать
profileMode. - Положите JAR-файл Numerical Storage в
plugins/Typewriter/extensions/и перезапустите сервер.
Окно произвольной суммы использует диалоги Paper, поэтому нужна версия Paper, которая их поддерживает (Minecraft 1.21.6 или новее).
Начиная с версии 0.9 новые артефакты используют технический идентификатор и версию 2 схемы JSON. При первом чтении старого файла он копируется по новому пути, сохраняется в backups/numericalstorage/ и удаляется. Сохраните копию папки assets/ TypeWriter перед обновлением.
Быстрый старт
Создадим банк, оплачиваемый вашей экономикой Vault:
- В веб-панели TypeWriter откройте страницу manifest и добавьте артефакт Player Numerical Storage. Оставьте
artifactIdпустым: TypeWriter сгенерирует его сам. - Добавьте Numerical Storage Definition. Задайте
displayName(напримерBank),prefixи свяжите артефакт вartifact. - В
levelsдобавьте первый уровень сlimitравным1000, затем второй с5000. ЗаполнитеdepositMessageиlevelUpMessage, если хотите собственный текст. - В
transactionзадайтеtransactionModeравнымVAULT. - В
menu.transactionButtonsдобавьте кнопку типаDEPOSITсamountTypeFIXED,amountравным100и предметом для отображения. Добавьте вторую кнопку типаWITHDRAW. - Добавьте действие Open Numerical Storage Menu. Свяжите
definition. - В его
layoutPoolдобавьте макетsimpleсidmainи задайтеmainLayoutIdравнымmain. В макет добавьте предмет сbuttonPrefix, равнымnumericalstorage_button:, иbuttonType, равнымDEPOSIT_FIXED:100. Сделайте то же самое дляWITHDRAW_FIXED:100,UPGRADE_LEVELиNAV_CLOSE. - Свяжите действие с диалогом NPC или событием-командой, опубликуйте и откройте банк в игре. Также можно выполнить
/typewriter ns open <definition>.
После каждой транзакции меню открывается заново, чтобы показать новый баланс. Расширение ищет запись Open Numerical Storage Menu, связанную с тем же определением. Если её нет, меню просто закрывается.
Как это работает
Меню
Меню — это обычный макет GUI. Действие Open Menu открывает его с заголовком и числом рядов из определения (menu.title, menu.rows, от 1 до 6), а ваш layoutPool определяет, где находится каждый предмет. Расширение превращает предмет в рабочую кнопку, если у предмета buttonPrefix равен numericalstorage_button: и задан buttonType из этого списка:
buttonType | Что делает кнопка |
|---|---|
DEPOSIT_FIXED | Вносит фиксированную сумму. Добавьте сумму после двоеточия, например DEPOSIT_FIXED:100. |
DEPOSIT_PERCENT | Вносит процент от баланса источника, например DEPOSIT_PERCENT:50. |
DEPOSIT_CUSTOM | Закрывает меню и запрашивает сумму в диалоге. |
DEPOSIT_ALL | Вносит весь баланс источника, вплоть до оставшейся вместимости. Нужен amountPlaceholder: в режиме VAULT кнопка пытается внести всю оставшуюся вместимость и завершается ошибкой, если баланс в экономике меньше. |
DEPOSIT_SUBMENU | Открывает подменю кнопок внесения. Id подменю следует после двоеточия. |
WITHDRAW_FIXED, WITHDRAW_PERCENT, WITHDRAW_CUSTOM, WITHDRAW_ALL, WITHDRAW_SUBMENU | То же, что выше, для снятия. Процент берётся от хранящегося баланса. |
TRANSFER_FIXED, TRANSFER_PERCENT, TRANSFER_ALL | Переносят баланс в другое определение. Кнопка берётся из записи transactionButtons типа TRANSFER с transferTarget. |
SUB_MENU | Открывает подменю, id которого следует после двоеточия, например SUB_MENU:deposit_options. |
UPGRADE_LEVEL | Повышает до следующего уровня или показывает предмет максимального уровня. |
NAV_CLOSE | Закрывает меню. |
Если у buttonType есть сумма (DEPOSIT_FIXED:100), расширение выбирает запись menu.transactionButtons с тем же типом, типом суммы и суммой и использует её template в качестве предмета. Без суммы используется первая подходящая запись. Если ничего не подходит, показывается обычный предмет-краситель с подписью по умолчанию.
Подменю определяются в menu.subMenus как соответствие id заголовку, числу рядов, кнопкам транзакций, размещённым в slots, кнопке «назад» и кнопке закрытия.
Для кнопки перевода нужен transferTarget другого определения (id его записи), а в целевом хранилище у игрока должно хватать места.
Команды
Все команды являются подкомандами /typewriter (псевдоним /tw). <definition> — запись определения. Необязательный [target] выбирает другого игрока; без него команда применяется к отправителю.
| Команда | Право | Описание |
|---|---|---|
/typewriter ns open <definition> [target] | typewriter.ns.open | Открывает меню хранилища через его запись Open Menu. |
/typewriter ns add <definition> <amount> [target] | typewriter.ns.add | Добавляет к балансу. Вместимость не проверяется. |
/typewriter ns remove <definition> <amount> [target] | typewriter.ns.remove | Вычитает из баланса, не ниже 0. |
/typewriter ns level <definition> <level> [target] | typewriter.ns.level | Задаёт уровень и сбрасывает баланс в 0. |
/typewriter ns reset <definition> [target] | typewriter.ns.reset | Сбрасывает уровень в 1 и баланс в 0. |
Команды /typewriter numstorage tx ..., upgrade и back_main используются кнопками меню внутри. Для игрока без открытого меню они ничего не делают.
При включённом profileMode команды add, remove, level и reset меняют баланс и уровень профиля цели, как и меню.
Ответы команд
Ответы add, remove, level, reset и open, а также ответы об ошибках ниже — это поля adminMessages в определении. Они написаны в MiniMessage. В каждом можно использовать <player>, <storage> (идентификатор определения) и <prefix>.
| Поле | Дополнительный плейсхолдер | По умолчанию |
|---|---|---|
resetMessage | нет | 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 | нет | Сообщение, которое показывается, когда у хранилища нет записи Open Menu. |
invalidAmountMessage | <amount> (введённое значение) | Invalid amount '<amount>'. Use a positive number. Показывается командами add и remove, когда сумма не является положительным числом. |
noArtifactMessage | нет | Сообщение, которое показывают add, remove, level и reset, когда к определению не привязан артефакт. |
noActiveProfileMessage | нет | <player> has no active profile. Показывается командами add, remove, level и reset, а также игроку, нажавшему действие меню, когда profileMode включён и у игрока нет активного профиля MMOProfiles. Ничего не записывается. |
Значения по умолчанию начинаются с префикса Typewriter. Три текста не принадлежат ни одному определению, поэтому вместо этого они являются сниппетами в snippets.yml: numericalstorage.command.player_only (команды кнопок меню, выполняемые не игроком) и тексты плейсхолдеров numericalstorage.placeholder.interest_disabled (Disabled), numericalstorage.placeholder.interest_error (Error) и numericalstorage.placeholder.capacity_unlimited (знак бесконечности). Единицы времени в interest_cooldown — это сниппеты numericalstorage.duration.days, hours, minutes, seconds (каждый — шаблон с {value}, по умолчанию {value}j) и numericalstorage.duration.separator.
Права
| Право | Даёт доступ к |
|---|---|
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. |
Права в interestRates | Дают игроку определённую процентную ставку. Используется первое право из списка, которое есть у игрока. |
Плейсхолдеры
Замените <id> на id записи определения. Им нужен PlaceholderAPI, а значения читаются из кэша, поэтому их безопасно использовать в скорбордах. При включённом profileMode значения balance, level, capacity и interest относятся к профилю, за который играет игрок, как и в меню.
| Плейсхолдер | Возвращает |
|---|---|
%typewriter_ns_balance_<id>% | Текущий баланс. |
%typewriter_ns_level_<id>% | Текущий уровень, начиная с 1. |
%typewriter_ns_capacity_<id>% | Вместимость текущего уровня или знак бесконечности, если уровни не определены. |
%typewriter_ns_interest_<id>% | Процентная ставка, действующая для игрока, в процентах. |
%typewriter_ns_interest_cooldown_<id>% | Время до следующего запланированного цикла начисления процентов или Disabled. |
%typewriter_ns_name_<id>% | displayName определения. |
%typewriter_ns_prefix_<id>% | prefix определения. |
Записи
Записей: 4, сгенерированы из исходного кода расширения.
Действия2
- Numericalstorage MenuOpens a Numerical Storage menu
- Numericalstorage Open MenuOpens a Numerical Storage menu (triggerable)
Артефакты1
- Player Numericalstorage ArtifactStores the numericalstorage amount per player
Манифесты1
- Numericalstorage DefinitionDefines a configurable numerical storage
Устранение неполадок
Меню открывается пустым или кнопки ничего не делают. Проверьте, что у каждого предмета buttonPrefix в точности равен numericalstorage_button: и задан корректный buttonType. Если префикс неверный, предмет остаётся обычным предметом без действия. Также проверьте, что mainLayoutId совпадает с id макета в layoutPool.
Меню закрывается после каждого внесения. Меню открывается заново через запись Open Numerical Storage Menu, связанную с тем же определением. Добавьте её, даже если вы открываете меню другой записью.
«Cannot add ... Would exceed limit». Хранилище заполнено до вместимости уровня игрока (levels[].limit). Повысьте уровень или увеличьте лимит. Если уровни не определены, лимита нет.
Внесение в режиме INTERNAL не удаётся. Баланс-источник игрока читается через amountPlaceholder и должен возвращать простое число. addCommand выполняется из консоли перед внесением и должна завершиться успешно. Используйте в команде {player} и {amount}.
«Economy system is not available.» transactionMode равен VAULT, но Vault или поставщик экономики отсутствует. Установите оба и перезапустите сервер.
Проценты не начисляются. Проценты применяются при входе игрока за циклы cron, прошедшие с его последней выплаты (не более 100 циклов). Должен быть включён interestEnabled и заполнен interestCron. Первый вход только фиксирует начальное время. Баланс, равный вместимости своего уровня, ничего не приносит.
Повышение уровня требует в качестве стоимости вместимость. Если у следующего уровня нет criteria, стоимость повышения равна limit текущего уровня и списывается с хранящегося баланса. Добавьте criteria следующему уровню, чтобы задать другое требование.
Плейсхолдеры показывают баланс другого профиля. При включённом profileMode плейсхолдеры и кнопка улучшения читают баланс и уровень профиля, выбранного игроком. Без MMOProfiles они читают собственный баланс игрока. С MMOProfiles и без активного профиля (экран выбора, после /mmoprofiles quit) они показывают 0, так как UUID игрока — это идентификатор его профиля Main, и его баланс нельзя ни показывать, ни пополнять. Запись отклоняется с noActiveProfileMessage, а проценты профиля начисляются при его выборе.
Плейсхолдер пуст сразу после перезапуска. Хранилище загружается в фоне при входе: первое чтение может прийти до конца загрузки; следующее покажет сохранённое значение.
Плейсхолдер пустой. Id в плейсхолдере должен быть id записи определения, а не его именем. Для проверки выполните /papi parse me %typewriter_ns_balance_<id>%.
Связанные расширения
- GUI — движок меню, используемый для макетов и кнопок.
- MMOProfiles — необязательный плагин, используется в
profileMode.