Кастомные команды через плагины
Рано или поздно встроенных команд игры перестаёт хватать. Игроки просят /tpahome, донатеры хотят /vip, новичкам нужен /rules с приветствием — а движок сервера из коробки такого не умеет. Хорошая новость: почти в любой игре с плагин-экосистемой (Minecraft на Bukkit/Spigot/Paper, Rust на Oxide/uMod и десятки других) кастомные команды — это рутинная задача, которая решается либо парой строк в конфиге, либо небольшим самописным плагином. Разберём оба пути и как не положить боевой сервер во время эксперимента.
Содержание
Зачем вообще свои команды
Список типичных сценариев, ради которых админы городят кастомные команды:
- Телепорт к точке или дому —
/home,/spawn,/warp shop. Без этого игроки тратят по 10 минут на пешие переходы и в итоге уходят на другой сервер. - Магазин —
/shop,/buy diamond 5,/sell all. Экономика держит игроков дольше, чем чистый PvP или выживание. - Статистика игрока —
/stats,/playtime,/kills— простая обратная связь, которая мотивирует возвращаться. - Приветствие новичка —
/rules,/discord, автосообщение при первом входе с ссылками на правила и комьюнити. - Служебные команды админа —
/vanish,/heal,/flyдля модерации, которых нет в ванильном сервере.
Все эти команды объединяет одно: они не входят в базовую логику игры, значит их либо добавляет плагин, либо их вообще не будет.
No-code: командные конфиги без единой строчки кода
Самый быстрый путь — плагины, которые умеют создавать команды прямо из YAML/JSON-конфига, без компиляции и Java/C#. На Minecraft (Paper/Spigot) для этого чаще всего берут CommandPanels или связку EssentialsX + CMILib, где часть команд уже готова (/home, /warp, /tpa), а недостающие докручиваются через алиасы и command blocks. Ещё один рабочий вариант — Skript, который формально «код», но синтаксис настолько близок к обычному английскому, что порог входа минимальный.
Пример простой команды на Skript — приветствие новичка с телепортом на спавн:
command /welcome:
trigger:
send "&aДобро пожаловать на сервер! Правила — /rules" to player
teleport player to {spawn}
Для Rust на Oxide/uMod похожая история: плагины вроде Kits или Backpacks уже дают готовые команды из коробки, а свои алиасы под конкретные нужды (например /tphome для дома игрока) настраиваются через oxide/config/PluginName.json — без единой строчки C#.
Плюс no-code подхода — скорость и отсутствие риска сломать что-то программной ошибкой. Минус — вы ограничены тем, что придумал автор плагина: сложную логику (например, команду с кулдауном, зависящим от VIP-статуса и текущей карты) через конфиг не всегда выразишь.
Нужен игровой сервер?
MAATRIX GAMES — 45+ игр, деплой за минуты, DDoS-защита, автобэкапы. Тарифы от 399 ₽/мес.
Создать серверКогда конфига не хватает: свой плагин
Если нужна логика, которой нет в готовых решениях — берём минимальный самописный плагин. Для Minecraft это Java-плагин под Paper API (Bukkit/Spigot API совместим), для Rust — C#-плагин под Oxide/uMod. Здесь не будем разворачивать полноценный гайд по каждой из этих плагин-платформ — подробный старт по Bukkit/Spigot плагинам и установка Oxide/uMod для Rust уже разобраны отдельно. Здесь — именно про структуру команды.
Базовая структура обработчика команды в Paper-плагине (onCommand):
public class HomeCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player player)) {
sender.sendMessage("Команда доступна только игрокам.");
return true;
}
if (!player.hasPermission("myplugin.home")) {
player.sendMessage("У тебя нет прав на эту команду.");
return true;
}
Location home = loadHomeLocation(player.getUniqueId());
if (home == null) {
player.sendMessage("Дом ещё не установлен. Используй /sethome.");
return true;
}
player.teleport(home);
player.sendMessage("Телепортация домой.");
return true;
}
}
Регистрация команды в plugin.yml:
name: MyHomePlugin
version: '1.0'
main: com.example.myhome.MyHomePlugin
api-version: '1.21'
commands:
home:
description: Телепорт к дому игрока
usage: /home
permissions:
myplugin.home:
description: Доступ к команде /home
default: true
Для Rust на Oxide структура похожая, но короче — плагин это один C#-файл в oxide/plugins/:
using Oxide.Core.Plugins;
namespace Oxide.Plugins
{
[Info("HomeCommand", "YourName", "1.0.0")]
class HomeCommand : RustPlugin
{
[ChatCommand("home")]
void HomeCmd(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, "homecommand.use"))
{
player.ChatMessage("У тебя нет доступа к этой команде.");
return;
}
// логика телепорта
}
void Init()
{
permission.RegisterPermission("homecommand.use", this);
}
}
}
Оба примера — минимальный каркас, без обработки ошибок и без сохранения данных (для домов и статистики понадобится своя база или файл конфига — SQLite или YAML, в зависимости от объёма данных). Но структура «команда → проверка прав → проверка условий → действие → фидбек игроку» одинакова практически везде.
Права доступа: не выдавайте всё подряд
Любая кастомная команда — потенциальная дыра, если права выставлены неверно. По умолчанию Bukkit/Spigot/Paper используют permission-ноды вида plugin.command, а раздачей групп занимается отдельный permissions-плагин — обычно LuckPerms. Подробно про группы и права разобрано в статье про permissions-плагины — здесь коротко: команду /vanish или /fly даём только группе admin, /home — всем, /vip-kit — только группе vip.
Типовая ошибка новичков — оставить default: true в plugin.yml для команды, которая должна быть только у модераторов. Проверяйте дефолтные права каждой новой команды до того, как плагин уедет на боевой сервер:
/lp user Steve permission check myplugin.home
/lp group admin permission set myplugin.vanish true
Для Oxide права регистрируются через permission.RegisterPermission (как в примере выше) и выдаются командой:
oxide.grant group admin homecommand.use
oxide.grant user Steve homecommand.use
Именование и конфликты команд
Когда команд становится много, легко словить конфликт — два разных плагина регистрируют одинаковую команду, и сервер использует ту, что загрузилась последней (порядок обычно алфавитный или по времени установки, и это не всегда предсказуемо). Несколько правил, которые экономят нервы:
- Используйте префикс плагина в названии команды (
/myp-homeвместо/home), если рискуете столкнуться с EssentialsX или другим крупным плагином. - Проверяйте занятые команды через
/help(Bukkit/Paper) или список зарегистрированных чат-команд в консоли Oxide перед добавлением новой. - Если конфликт всё же случился — используйте алиасы в
plugin.yml(aliases: [myhome]) вместо переименования основной команды, чтобы не ломать привычки игроков.
Тестирование перед боевым сервером
Главное правило, которое почему-то регулярно игнорируют даже опытные админы: новая команда сначала выкатывается на тестовый сервер, и только потом на боевой. Причины две — во-первых, ошибка в обработчике команды может уронить весь сервер (NullPointerException в Java или необработанное исключение в C# на популярных серверах иногда крашит процесс целиком), во-вторых, неправильные права могут случайно открыть админскую команду всем игрокам.
Практическая схема:
- Разверните второй, тестовый сервер — по конфигурации идентичный боевому (та же версия ядра, тот же набор плагинов). Для Minecraft/Rust это отдельный инстанс с теми же модами, но с тестовым миром — по сути, второй арендованный сервер.
- Скопируйте плагины и конфиги с боевого на тестовый, добавьте новый плагин туда же.
- Прогоните сценарий вручную: зайдите под обычным игроком без прав и под админом, проверьте обе ветки поведения команды.
- Проверьте лог сервера на ошибки (
logs/latest.logдля Paper, консоль Oxide для Rust) — если в логе есть stack trace при вызове команды, на боевой её выкатывать рано. - Только после чистого прогона — копируйте плагин и обновлённый конфиг на боевой сервер, желательно на низкой нагрузке (не в прайм-тайм выходных).
Держать отдельный тестовый сервер для одной команды может показаться избыточным, но по факту это дешевле, чем чинить боевой сервер посреди вечера, когда там 40 онлайн-игроков и все видят ошибку.
Нужен игровой сервер?
MAATRIX GAMES — 45+ игр, деплой за минуты, DDoS-защита, автобэкапы. Тарифы от 399 ₽/мес.
Создать серверЧастые вопросы
Можно ли добавить команду без перезапуска сервера?
Да, если плагин поддерживает hot-reload (у Oxide это встроено — oxide.reload PluginName, у Bukkit/Paper зависит от плагина, но большинство командных фреймворков вроде CommandPanels тоже умеют перечитывать конфиг на лету через /reload внутриигровую команду плагина). Полный /restart сервера всё равно надёжнее для критичных изменений.
Как ограничить команду только определённым миром или картой?
В Bukkit/Paper проверяется через player.getWorld().getName() внутри обработчика команды. В Oxide — аналогично через текущую сцену/зону, если игра это поддерживает (например, зоны на карте Rust через отдельный zone-плагин).
Нужно ли писать свой плагин, если есть Skript?
Не обязательно — Skript закрывает большинство простых сценариев (телепорт, сообщения, базовые условия) без компиляции. Свой Java/C# плагин имеет смысл, когда логика сложная (своя база данных, интеграция с внешним API, производительность на большом онлайне).
Что если команда работает на тесте, но падает на боевом?
Чаще всего причина — расхождение версий плагинов или ядра между тестовым и боевым сервером. Держите версии синхронизированными и обновляйте оба сервера одновременно.
Куда сохранять данные команды (дома, статистику)?
Для небольших серверов достаточно YAML или JSON-файла в папке плагина. При росте онлайна за пару сотен игроков лучше переходить на SQLite или MySQL — плагин будет меньше нагружать диск частыми перезаписями.