← Гордеев Виталий · все кейсы
Кейс · сентябрь 2026
Игровые серверы · Java · Paper/Purpur

Серверы по ТЗ и 75 своих плагинов

Заказчик присылает ТЗ списком пунктов, я по нему собираю игровой сервер: миры, меню, боссов, магазины, донат-группы. Часто у заказчика уже есть купленная «сырая» сборка, и тогда я довожу её и разгребаю чужие баги. Всё, что повторяется, выношу в свою библиотеку плагинов и потом беру в следующие проекты.

75своих плагинов в исходниках
203 573строки Java в 1 195 файлах
46плагинов портированы на Java 8 под старые серверы
25 из 26пунктов ТЗ закрыто в последней сборке; один снял сам заказчик
01 · Процесс

От списка в ТЗ
до архива со сборкой

За сентябрь сдал четыре сборки, пятая ещё в работе. Процесс везде одинаковый, так что я записал его в инструкцию и по ней собираю каждый следующий сервер.

01

ТЗ построчно в файл

Каждый пункт заказчика идёт отдельной строкой со статусом. Сдаю, когда все строки закрыты или явно сняты.

02

Инвентаризация базы

Смотрю, что лежит в базе: чужие плагины, чужие меню, битые ссылки. Лишнее отключаю и складываю в отдельную папку, удалять не спешу: вдруг заказчик вспомнит.

03

Один стиль на все меню

Палитру, шрифт и кнопки задаю один раз, а скрипт раскатывает их на все 45–54 меню разом. Если править полсотни меню руками, они всё равно разъедутся.

04

Контент по ТЗ

Сначала миры, потом ивенты и боссы, потом магазины, донат и NPC. Порядок такой, потому что каждый шаг опирается на предыдущий.

05

Сдача с руководством

Отдаю архив на Яндекс.Диске, текстовое руководство на 14–24 раздела и лицензионный ключ.

JavaPaperPurpurVelocityItemsAdderDeluxeMenusMythicMobsLuckPermsPlaceholderAPIMavenPythonRCON
02 · Масштаб

Что внутри одной сборки

Цифры по сборкам, которые я сдал в сентябре. Серверы все разные, от скайблока до сети мини-игр на восемь серверов.

СборкаЧто в ней
Скайблок51 плагин, 8 своих; 45 меню, 65 панелей окон; 5 боссов; 22 рецепта крафта; 58 предметов донат-снаряжения
Грифер «Мега»45 меню к единому канону кнопок, 20 иконок, 85 донат-товаров, 8 донат-групп
Грифер «Весна»62 плагина, 48 меню, 20 иконок, 36 особых предметов, 3 кейса, 8 донат-групп
Сеть мини-игр8 серверов за прокси Velocity, 54 меню; вычищены 19 чужих аккаунтов и 56 чужих игроков из купленной базы
Анархия с мирамиМир «Четыре стихии» 4000×4000, 65 536 заранее сгенерированных чанков; стартовой группе выдано 74 права разом

Порт на Java 8. Часть заказчиков сидит на старых серверах, где работает только Java 8. Мои плагины написаны на современной Java: переменные через var, новый switch, записи. Переписывать руками 1 823 таких места я не стал. Подключил компилятор-переводчик jabel и общий модуль совместимости для API, которого в Java 8 нет. Так 46 плагинов собрались под старый байткод, и синтаксис руками переписывать не пришлось.

03 · Разбор

Код в порядке,
а в игре не работает

Почти все эти поломки сразу не видны ни в конфигах, ни в логах. Они вылезают, только когда заходишь в игру и жмёшь кнопку.

01

Жмёшь «купить», и ничего

Симптом
Покупки в донат-магазине молча не срабатывали, игрок не получал никаких сообщений.
Причина
На сервере не было маленького расширения к PlaceholderAPI. Меню не могло подставить имя игрока, и магазин искал человека с именем «%player_name%».
Поставил одно расширение, и все покупки заработали. Баг возвращался дважды, так что теперь на него есть отдельная памятка, проверяю её в каждой сборке.
Табло сервера с неподставленными переменными: %player%, %group%, %online%
Табло на раннем этапеТак выглядит сервер, где переменные ещё не подставляются: вместо имени и уровня висят сырые %player% и %online%.
02

88 кнопок без звука

Симптом
Кнопки «назад» и «закрыть» работали, но беззвучно.
Причина
Меню выполняет команды кнопки по порядку и обрывает список, когда окно закрылось. Звук стоял после закрытия, и до него очередь не доходила.
Переставил звук первым во всех 88 кнопках.
DeluxeMenus/gui_menus/bosses.yml · дословно
    left_click_commands:
      - '[sound] ITEM_BOOK_PAGE_TURN'
      - '[openguimenu] fun'
  close:
    material: 'PAPER'
    model_data: 5201
    slot: 26
    display_name: '&7✖ &fЗакрыть'
    left_click_commands:
      - '[sound] BLOCK_CHEST_CLOSE'
      - '[close]'
03

Никто не мог зайти даже в лобби

Симптом
Сеть из восьми серверов пускала игрока на прокси и тут же выкидывала.
Причина
На всех семи внутренних серверах была выключена пересылка данных игрока от прокси. А в имени ключа секрета стояла опечатка: вместо пути к файлу сервер читал строку.
Включил пересылку везде и оставил один общий секрет, который читается из файла.
04

База прав падала от нехватки памяти

Симптом
Плагин прав регулярно падал с OutOfMemoryError.
Причина
Память была распределена наоборот: основному игровому серверу 2 ГБ, а пустому хабу 7 ГБ.
Раздал заново: 6 ГБ игре, 2 ГБ хабу, 1 ГБ прокси.
05

Скины показывали стандартные текстуры

Симптом
Купленные скины оружия выглядели как обычные предметы.
Причина
Конфиг перенесли из другой сборки вместе с 294 чужими обёртками на несуществующие ресурсы. Они перебивали свои.
Чужие удалил, свои 193 обёртки теперь грузятся из своей папки.
06

Один пустой символ ронял весь ресурспак

Симптом
После добавления иконки ломался весь пак целиком.
Причина
Символ иконки записали текстом «» с обратной косой чертой, а нужен был сам символ юникода.
Теперь символы генерирует код, а перед сборкой отдельный скрипт ищет пустые и повторы.
07

Опыт перестал копиться

Симптом
Игроки упирались в уровень и дальше не росли, хотя система уровней была рассчитана на 300.
Причина
В конфиге стоял потолок 100, а начисление опыта первой же строкой проверяло: «если уровень не ниже потолка, ничего не делать».
Поднял потолок до 1000. Такие «мелочи» почти всегда системные: одна настройка ломает весь прогресс.
свой плагин · HuntCommand.java · дословно
// Команда охотника: точные координаты и расстояние до каждого счастливчика.
case "track", "coords", "радар" -> {
    if (!(sender instanceof Player p)) { raw(sender, "&cТолько для игроков."); return true; }
    if (!p.hasPermission(USE)) { deny(sender); return true; }
    manager.showTrack(p);
}

Так выглядит код на современной Java: новый switch и сопоставление с образцом. Как раз такие места jabel и переводит под Java 8.

04 · Правила

Ничего не сделано,
пока не проверено в игре

Конфиг может быть без единой ошибки, а кнопка в игре при этом не жмётся. На этих сборках такое было не раз.

01

Проверка только в игре

Панель проверяю наложением сетки, меню открываю, ивент запускаю. Для этого у меня есть свой игровой клиент: он сам открывает окна и снимает их.

02

Конфиги не править регулярками вслепую

YAML сначала загружаю парсером, правлю как структуру и только потом записываю. Сдвинешь отступ на один пробел, и плагин не стартует.

Нужен сервер или плагин?

Соберу сервер по ТЗ, доведу купленную сборку до рабочего состояния или напишу плагин под вашу механику. Работаю удалённо, из Самары.

Telegram · @vitaldemort