Продвинутая система скупщика ресурсов для Paper 1.21+: живое GUI, динамический рынок, ротация ассортимента, магазин бустеров, автопродажа с тремя режимами, интеграция с PlayerPoints (отдельный донатный скупщик или выплата целиком в поинты), прогрессия игрока и несколько режимов хранения — от YAML на одном сервере до MySQL + Redis в сети.
SoulBuyer — это не «положи предмет в слот и жди». Игрок открывает меню и видит сетку скупаемых ресурсов с актуальными ценами, очками и рыночным коэффициентом. ЛКМ по предмету — продажа всего такого ресурса из инвентаря; ПКМ — выбор количества в отдельном подменю. Есть фильтры по категориям, сортировки, пагинация и кнопка «продать всё».
Чем больше на сервере продают один ресурс — тем ниже его рыночный коэффициент (с настраиваемым минимумом и постепенным восстановлением). За продажи начисляются очки прогрессии и опыт категорий (руды, мобы, растения, блоки, прочее); очки можно тратить в магазине бустеров на временные усиления. Выплата — через Vault или PlayerPoints (см. PlayerPoints и донатный скупщик).
Автопродажа — отдельный донат-плюс: игрок сам выбирает, когда сдавать ресурсы — при подборе, при открытии меню скупщика или содержимое сундука при открытии. Настраиваются категории, уведомления и минимальная цена.
Ассортимент не застаивается: по таймеру меняется набор скупаемых предметов, сбрасываются рыночные коэффициенты, игроки получают оповещение в чат. Внизу меню — живая панель статистики: сколько осталось до обновления, что продано сегодня, сколько ресурсов сейчас в ротации.
Кратко, зачем ставить на сервер:
- Из коробки — ~380 предметов, GUI, ротация, рынок и lang (ru/en) с первого запуска; без ручной возни с конфигами
- Всё настраивается — цены, каталог, слоты GUI, права, лимиты рынка, ротация, автопродажа, economy; тексты в
lang/, цифры вconfig.yml/items.yml - GUI вместо команд — продажа, фильтры, сортировки, количество, автопродажа; команды только как алиасы
- Живой рынок — цена падает от массовых сдач, decay возвращает к норме; игрок видит коэффициент в lore
- Ротация ассортимента — по таймеру новый набор из пула; оповещение в чат; открытые меню обновляются на месте
- Донатный скупщик — Vault + PlayerPoints: два меню (
/buyerи/donbuyer) или один скупщик целиком на поинты; два флага в config - Автопродажа — донат-плюс: подбор / меню / сундук; категории, мин. цена, уведомления; при dual — выбор, куда платить (монеты или поинты)
- Бустеры — магазин временных усилений в меню скупщика; оплата очками прогрессии, Vault или PlayerPoints (настраивается)
- Персональные лимиты продаж — дневной cap на item-id (анти-демпинг); права LuckPerms и бустер лимитов
- Прогрессия — очки, XP категорий, VIP-множители через LuckPerms; мотивация фармить, не только лутать
- Живая статистика — таймер до ротации, «продано сегодня», размер ассортимента прямо в меню (+ PlaceholderAPI)
- Анимация категорий — иконки фильтров крутят реальные предметы из текущей ротации
- Оптимизация — весь I/O БД асинхронно; main thread не блокируется; HikariCP; Redis только когда нужна сеть
- Хранение на выбор —
flat/sqlite/mysql+ Redis для нескольких Paper-серверов с общим рынком - Безопасные продажи — secure storage на транзакцию; при ошибке или выходе предметы возвращаются
- API для других плагинов —
SoulBuyerApi: открыть меню, котировки, рынок, прогресс, автопродажа
| Зона | Что делает |
|---|---|
| Верхний ряд | Фильтры категорий + блок «Ваш прогресс» (очки, множитель) |
| Сетка 21 слот | Иконки скупаемых предметов: цена, очки, рынок, количество в инвентаре. ЛКМ — продать всё, ПКМ — подменю количества |
| Стрелки ← → | Пагинация (на 4-м ряду, по бокам от сетки) |
| Нижний ряд | Сортировка (одна кнопка-переключатель), «продать всё», бустеры, автопродажа, панель «До обновления» |
| Категории | «Все» — иконка Vault (хранилище); остальные — живая анимация: иконка меняется и показывает реальный предмет из текущего ассортимента категории |
Сортировка (комparator, клик — следующий режим): дороже → дешевле → больше очков → меньше очков.
Бустеры (звезда незера в нижнем ряду): ЛКМ — магазин временных усилений. Доступно из обычного и донатного меню. Подробности — в разделе Бустеры.
Автопродажа (изумруд в нижнем ряду): ЛКМ — экран настроек, ПКМ — вкл/выкл. Подробности — в разделе Автопродажа.
Тексты и цвета — в lang/ru.yml, lang/en.yml. Hex-цвета, градиентный заголовок, lore у категорий и предметов настраиваются без пересборки JAR.
Отдельная механика для доната (soulbuyer.autosell, по умолчанию OP). Игрок настраивает поведение сам — настройки сохраняются per-player (YAML или MySQL).
Один из трёх режимов (переключается кнопкой в меню настроек):
| Режим | Иконка | Когда срабатывает |
|---|---|---|
| При подборе | Воронка | Предмет попал в инвентарь с земли или с рыбалки |
| При открытии меню | Изумруд | Открыт GUI скупщика — продаёт всё подходящее из инвентаря игрока |
| При открытии сундука | Сундук | Открыт контейнер — продаёт всё подходящее из слотов сундука. Инвентарь игрока не трогается |
Работает с сундуком, бочкой, шалкером, эндер-сундуком, воронкой, раздатчиком, выбрасывателем, вагонеткой-сундуком. Учитываются включённые категории и мин. цена игрока.
| Опция | Смысл |
|---|---|
| Вкл/выкл | Мастер-переключатель (центр меню или ПКМ по изумруду в скупщике) |
| Категории | Руды, мобы, растения, блоки, прочее — клик вкл/выкл автопродажу для категории |
| Уведомления | Action bar / чат / выкл |
| Мин. цена | Не продавать предметы дешевле порога (с учётом рынка и множителей) |
| Куда продавать | Только при dual buyer: обычный скупщик (Vault) или донатный (PlayerPoints). Клик по слитку в центре 4-го ряда |
На слоте с книгой — краткая справка для игрока. Если в инвентаре нечего продавать, лишних сообщений в чат нет.
В обоих меню скупщика (обычном и /donbuyer) кнопка автопродажи показывает текущий режим выплаты; настройка — в том же экране автопродажи, куда игрок зашёл из любого меню.
- Донат-плюс без pay-to-win: те же цены и рынок, меньше рутины.
- Сортировка базы: режим «сундук» — открыл хранилище, скупаемый мусор внутри сразу продался, нужное осталось в сундуке.
- АФК-фарм: режим «подбор» — подобрал ресурс, он уже продан.
- Казуал-игроки: режим «меню» — зашёл в
/buyer, всё лишнее сдалось само.
В config.yml → секция autosell: вкл/выкл фичи на сервере, дефолты для новых игроков, шаги мин. цены, задержка после подбора.
Магазин временных усилений — открывается из обычного (/buyer) и донатного (/donbuyer) меню: кнопка «Бустеры» (звезда незера) → отдельный экран с тремя предложениями.
Покупка списывает валюту из config.yml → boosters.currency:
| Значение | Списание |
|---|---|
progression_points |
Очки SoulBuyer (дефолт — зарабатываются за продажи, раньше некуда тратить) |
vault |
Монеты через Vault |
playerpoints |
PlayerPoints |
| ID | Эффект | Длительность | Цена (дефолт) |
|---|---|---|---|
multiplier |
+0.5 к личному множителю дохода | 1 ч | 125 очков |
money |
×1.25 к монетам/поинтам от продажи | 1 ч | 175 очков |
limit |
×2 к персональному дневному лимиту на item-id | 30 мин | 75 очков |
Цены, длительность, сила эффекта, материалы и слоты в GUI — в config.yml → boosters.offers и gui/boosters.yml.
На кнопке каждого бустера в lore: эффект, цена, длительность, активен ли сейчас и сколько осталось. Повторная покупка обновляет таймер того же типа.
Параллельная механика анти-демпинга — секция sell-limits в config.yml:
- У каждого игрока дневной лимит на продажу каждого
item-id(дефолт 64 шт./сутки). - LuckPerms-ноды
soulbuyer.limit.vip/soulbuyer.limit.premiumподнимают cap (128 / 256). - Бустер лимитов умножает итоговый лимит.
sell-limits.enabled: false— лимиты полностью отключены.
При превышении лимита продажа урезается до допустимого объёма, лишнее возвращается в инвентарь.
| Нода | Доступ |
|---|---|
soulbuyer.boosters |
Магазин бустеров (default: true) |
Дефолты в Java: бустеры включены, валюта — очки прогрессии, все три предложения и GUI на месте после первого запуска. Активные бустеры сохраняются per-player (data/boosters/ или таблица soulbuyer_boosters).
SoulBuyer не привязан только к Vault. Если на сервере стоит PlayerPoints, плагин умеет платить за сдачу ресурсов донатными поинтами — без костылей, отдельными командами и с тем же рынком, ротацией и прогрессией.
Один каталог items.yml, одни цены и коэффициенты — меняется только валюта выплаты (монеты сервера или PlayerPoints).
player-points-enabled |
donate-buyer-enabled |
Что видит игрок |
|---|---|---|
false |
— | Классика: /buyer → выплата в Vault |
true |
false |
Один скупщик: /buyer → всё в PlayerPoints (Vault не нужен) |
true |
true |
Два скупщика: обычный за монеты + донатный за поинты |
economy:
player-points-enabled: false # включить PlayerPoints
donate-buyer-enabled: false # true = второе меню только за поинтыНа донат-серверах часто нужно разделить экономику: фарм → монеты, донатный контент → поинты. SoulBuyer закрывает оба сценария одним JAR:
| Меню | Команда | Выплата | Кому |
|---|---|---|---|
| Обычный | /buyer, /sell, /soulbuyer |
Vault (монеты) | Все с soulbuyer.use |
| Донатный | /donbuyer, /dbuyer, /ppbuyer |
PlayerPoints | С soulbuyer.donate |
- Тот же ассортимент и живой рынок — цена падает от массовых продаж в обоих меню.
- Очки прогрессии и XP категорий начисляются как обычно (это не валюта, а мета-прогресс SoulBuyer).
- Отдельный заголовок и lore у донатного меню — игрок сразу видит, что платят поинтами.
- Автопродажа следует выбору игрока в настройках: при dual-режиме — Vault или PlayerPoints; если включён только PlayerPoints — всегда в поинты.
Дефолты в Java: PlayerPoints выключен, работает только Vault — как раньше. Включение — две строки в config.yml, перезапуск сервера. Команды /donbuyer и алиасы уже в plugin.yml; если донатный режим выключен, /donbuyer ответит, что фича недоступна.
| Плагин | Когда нужен |
|---|---|
| Vault + экономика | Дефолт; обязателен при dual-режиме и классическом режиме |
| PlayerPoints | player-points-enabled: true |
Оба — softdepend в plugin.yml: плагин стартует, ждёт нужную экономику и только потом открывает GUI.
- Каждый ресурс имеет базовую цену и коэффициент рынка (старт 1.0).
- Массовые продажи снижают коэффициент до настроенного минимума.
- Decay постепенно возвращает цену к 1.0, если ресурс перестают сдавать.
- В режиме mysql + сеть коэффициенты синхронизируются через Redis pub/sub.
Игрок видит множитель рынка прямо в lore предмета в GUI.
Полный каталог (~380 ванильных ресурсов в items.yml) — это пул. В скупщике одновременно активен случайный поднабор (по умолчанию 48 предметов, минимум из каждой категории).
| Параметр | Дефолт | Смысл |
|---|---|---|
catalog-rotation.enabled |
true |
Ротация вкл/выкл |
interval-seconds |
3600 |
Интервал смены (1 час) |
active-item-count |
48 |
Сколько предметов в меню |
reset-market-on-rotation |
true |
Сброс коэффициентов рынка при смене |
notify.enabled |
true |
Сообщение в чат при обновлении |
Состояние ротации хранится в data/rotation.yml. Открытые меню обновляются без закрытия.
Вместо «Страница 1/3» — часы с живым таймером (обновление каждую секунду):
- До обновления — оставшееся время до ротации
- Сегодня продано — монеты, очки, позиций
- В ассортименте — сколько ресурсов сейчас в ротации
Плейсхолдеры для lore в lang:
| Плейсхолдер | Описание |
|---|---|
{rotation_left} |
Таймер до ротации или «отключена» / «скоро» |
{sold_today_money} |
Монет за сегодня |
{sold_today_points} |
Очков за сегодня |
{sold_today_stacks} |
Позиций продано |
{active_items} |
Предметов в текущем ассортименте |
- Очки за каждую продажу (из
base-pointsпредмета + бонус от базовой цены ×points-per-currency). - XP категорий — растёт от заработанных очков; бонус к деньгам считается от уровней XP (не от сырого числа), с потолком
max-category-bonus. - Permission-множители — VIP, Premium и др. (берётся максимальный из выданных).
- Бонус доминирующей категории — доп. доход от уровня XP главной категории (
category-xp-per-level,dominant-category-bonus-per-level). - Очки можно тратить в магазине бустеров (если
boosters.currency: progression_points). - Защита от разгона:
max-unit-price,max-payout-per-saleна одну транзакцию.
- Secure storage на время транзакции — предметы не теряются при лаге или ошибке.
- При выходе / сбое — возврат непроданного в инвентарь.
- Продажи пишутся в лог (
sales.logили таблицаsoulbuyer_sales) — основа для статистики «сегодня продано». - Весь I/O с БД — асинхронно, main thread не блокируется.
| Режим | Когда использовать |
|---|---|
flat |
Один сервер, YAML + лог продаж (дефолт) |
sqlite |
Один сервер, файл data/data.db |
mysql |
Сеть серверов, общая БД + Redis для рынка |
Прогресс игрока, коэффициенты рынка, ротация, лог продаж — всё переживает рестарт.
Основная: /soulbuyer. Алиасы открытия меню (настраиваются): /buyer, /sell, /sb, /rbuyer, /bs.
Донатный скупщик (только при economy.donate-buyer-enabled: true): /donbuyer. Алиасы: /dbuyer, /ppbuyer, /donatesell.
| Команда | Действие |
|---|---|
/soulbuyer |
Открыть GUI скупщика (Vault или PlayerPoints — по режиму economy) |
/buyer, /sell, … |
То же (алиасы) |
/donbuyer, /dbuyer, … |
Донатное меню — выплата в PlayerPoints (dual-режим) |
/soulbuyer admin reload |
Перезагрузить config, gui, lang |
Алиасы наследуют подкоманды:
/buyer admin reload=/soulbuyer admin reload.
| Нода | Доступ |
|---|---|
soulbuyer.use |
GUI и продажа (обычный скупщик) |
soulbuyer.donate |
Донатное меню /donbuyer (PlayerPoints, dual-режим) |
soulbuyer.admin |
/soulbuyer admin reload |
soulbuyer.autosell |
Автопродажа (донат, OP по умолчанию) |
soulbuyer.boosters |
Магазин бустеров (default: true) |
soulbuyer.limit.vip |
Дневной лимит продаж 128 шт./item-id |
soulbuyer.limit.premium |
Дневной лимит продаж 256 шт./item-id |
soulbuyer.multiplier.vip |
Множитель ×1.1 (дефолт) |
soulbuyer.multiplier.premium |
Множитель ×1.25 (дефолт) |
При нескольких multiplier-нодах берётся максимальный множитель.
softdepend — если PAPI на сервере, регистрируется expansion soulbuyer.
| Плейсхолдер | Описание |
|---|---|
%soulbuyer_rotation_left% |
Таймер до ротации (текст) |
%soulbuyer_rotation_seconds% |
Секунд до ротации (число) |
%soulbuyer_sold_today_money% |
Монет продано сегодня |
%soulbuyer_sold_today_points% |
Очков за сегодня |
%soulbuyer_sold_today_stacks% |
Позиций продано сегодня |
%soulbuyer_active_items% |
Предметов в текущем ассортименте |
Плейсхолдеры PAPI можно вставлять в строки lang/*.yml — они подставятся при отрисовке GUI.
| Файл | Содержимое |
|---|---|
config.yml |
Хранение, рынок, ротация, прогрессия, бустеры, лимиты продаж, права, анимация иконок категорий |
items.yml |
Каталог: id, material, категория, base-price, base-points |
gui/general.yml, gui/buyer.yml, gui/quantity.yml, gui/autosell.yml, gui/boosters.yml |
Слоты, материалы кнопок, action-типы |
lang/ru.yml, lang/en.yml |
Заголовки, lore, сообщения, hex-цвета |
data/rotation.yml |
Текущая ротация и время следующей смены |
data/market.yml |
Коэффициенты рынка (режим flat) |
data/players/ |
Прогресс игроков (режим flat) |
data/boosters/ |
Активные бустеры игроков (режим flat) |
data/sell-limits/ |
Продажи за текущий день per item-id (режим flat) |
Дефолты заданы в Java — после первого запуска всё работает из коробки: ~380 предметов, ротация, GUI, каталог, статистика.
Ключевые секции config.yml:
storage-type: flat # flat | sqlite | mysql
economy: # Vault / PlayerPoints / dual buyer
catalog-rotation: # смена ассортимента по таймеру
category-icon-animation: # живая смена иконок категорий
market: # decay, min-coefficient, flush
progression: # множители, очки, XP категорий, лимиты выплат
boosters: # валюта покупки, offers (цена, эффект, длительность)
sell-limits: # дневные лимиты, permission-tiers- Расширенные admin-команды
| Компонент | Обязательность |
|---|---|
| Paper 1.21+ | да |
| Java 21 | да |
| Vault + экономика | да по умолчанию; не нужен, если только PlayerPoints (player-points-enabled: true, donate-buyer-enabled: false) |
| PlayerPoints | опционально; нужен при player-points-enabled: true |
| MySQL + Redis | только storage-type: mysql в сети |
| PlaceholderAPI | опционально |
Для других плагинов — интерфейс SoulBuyerApi, регистрируется в Bukkit ServicesManager.
import bm.b0b0b0.soulBuyer.api.SoulBuyerApi;
import bm.b0b0b0.soulBuyer.api.SoulBuyerApiProvider;
import org.bukkit.Bukkit;
SoulBuyerApi api = SoulBuyerApiProvider.get();
// или: Bukkit.getServicesManager().load(SoulBuyerApi.class)
if (api.isReady()) {
api.openBuyerMenu(player);
double points = api.cachedPoints(player);
double multiplier = api.cachedMultiplier(player);
api.quoteItem(player, "diamond").ifPresent(quote -> { /* unitPrice, unitPoints */ });
api.fetchProgress(player.getUniqueId()).thenAccept(progress -> { /* async */ });
}| Метод | Назначение |
|---|---|
isReady() |
Плагин загружен и готов |
openBuyerMenu(Player) |
Открыть GUI скупщика |
quoteItem / quoteStack |
Цена и очки за единицу с учётом рынка и множителей |
marketCoefficient(itemId) |
Текущий коэффициент рынка |
cachedPoints / cachedMultiplier / cachedCategoryXp |
Данные из кэша (после продаж или fetchProgress) |
fetchProgress(UUID) |
Async загрузка прогресса из хранилища |
isSellable / isInActiveCatalog |
Предмет в пуле / в текущей ротации |
isAutosellFeatureEnabled / canUseAutosell / isAutosellEnabled |
Автопродажа |
plugin.yml другого плагина: depend: [ SoulBuyer ] или softdepend.