Сборки серверов

СливПлатные

Новые сообщения

Сейчас онлайн

  • SunsetRQ7_
  • Shynert
  • bishepp
  • Kenny McCormik
  • kolyamips
  • DoBidoV
  • sw3ens
  • Felleus Development
  • Iriskas
  • NevileeV
  • Kamilo_Meow
  • eblan228$$$
  • OderPrince
  • SeaCore
  • MrPorshe
  • itsDesterYT
  • kirilltwice
  • DAFSSS11
  • aristokrafter
  • ANDEREEEEEEEEEEEEEY
  • undefined322
  • mmatvie
  • hatless
  • Gazmanov
  • Yung
  • artemla49
  • trevorxxx
  • Steve150634
  • Karakatoka
  • br1ckv73
  • damaizer
  • Zebka_
  • Rompix
  • LiSnow
  • WoWKiller22
  • savagetheunicorn
  • fgfhgvjgggjgjg
  • Bobraaaa
  • PIRATESKILL
  • Blackcat
  • stussywaves
  • ExstazzyOnlyNe
  • KonyTT
  • hai1004
  • Axile7
  • SLIMIK
  • neklol
  • Nabes
  • Absolutely
  • ngohoanglong2704
  • GaurangPro20
  • mohammed_iron
  • crash253egf
  • Arisu
  • fedorov
  • Kont
  • Flysok
  • Pomachka58BW
  • OverwriteMC
  • 121111123
  • Pazetch
  • Padomipa

Инструкция Создание плагинов ✎ Пособие для начинающих

  • Автор темыILucious
  • Дата начала
ILucious
* * *
ПРЕДИСЛОВИЕ
* * *
Данная статья не является гайдом по изучению языка программирования Java, для получения необходимых знаний можете воспользоваться следующими ресурсами на форуме: "Изучение языка Java". Автор заранее предполагает, что вы обладаете необходимыми начальными знаниями синтаксиса языка, поэтому прошу воздержаться от дальнейших комментариев по этому поводу. В конце статьи будут продублированы используемые ссылки и ресурсы.

* * *
НАЧАЛО
* * *
В данной статье мы разберём как создать свой первый плагин для ядра Spigot. Автор знает, что существуют форки данного ядра, но так-как гайд рассчитан для новичков, то мы будем брать конкретно это API.

𝟙 - Установка среды разработки

Для того, чтобы работать на языке Java предполагается использование так называемых интегрированных сред разработки (IDE). Существует достаточно количество десктоп приложений для этого, приведу в пример некоторых из них:
  • Eclipse, довольно популярная среди разработчиков, является open-source проектом, поэтому бесплатна. Из минусов хочется отметить немалую нагрузка на CPU, иногда медленно компилирует приложение, возникновение ошибок и вылетов из-за дополнительных плагинов и прочего.
  • NetBeans, является официальной средой разработки для Java 8, так же является open-source проектом. Потребляет много ОЗУ во время работы.
  • IntelliJ IDEA, мощная и эргономичная среда разработки с функциями для повышения производительности, нет загромождения пользовательского интерфейса. На данный момент представлена в двух версиях: Ultimate / Community, одна из которых является платной, а другая бесплатной. Из минусов хочется отметить большую нагрузку на системные ресурсы и так-же довольно сложна для новичков в освоении.

Из всего выше перечисленного мы будем использовать именно последний вариант - IntelliJ IDEA Community.
При переходе на страницу сайта мы увидим вот такое:

1647331227539
Здесь вам необходимо скачать Community версию, так-как она бесплатна и не имеет срока пользования. Нажимайте на кнопку Download и ожидайте загрузки.

После нам необходимо открыть установщик приложения, запустите .exe файл который только что скачался.
Далее следуйте инстукциям ниже:

16473316427941647331659534164733169017916473316988421647331786683
На данном этапе установка нашего приложения завершена, поздравляю вас, если всё получилось.

𝟚 - Необходимые настройки IDE

При первом запуске, у нас запросят импорт настроек IDE, пропускаем это.
1647332096404

Теперь мы видим главный экран нашего приложения:
1647332245313

Посмотрите на небольшое меню слева. Тут необходимо перейти по вкладке Plugins, нажмите на неё.
1647374006682

В строке поиска, которая находится чуть ниже слова Marketplace, мы должны набрать следующее: Minecraft Development
Нажимаем кнопку Install, ожидаем загрузки и позже перезагружаем приложение.

1647374098185

𝟛 - Создание первого проекта

На главном экране нашего приложения нажимаем кнопку New Project
1647374306918

Теперь перед собой мы видим следующее:
1647374428971

Теперь нам необходимо в левом меню выбрать пункт Minecraft и отметить галочкой следующее:
1647374487934

Нажимаем кнопку Next и переходим на следующий этап создания проекта:
1647374526791

Что такое GroupId: В основном это что-то наподобие названия компании (com.google, org.apache и прочее). Можно использовать такой путь: me.{author_name} или же любой другой, как ваша душа пожелает, так-как это ни на что не влияет.
Что такое ArtifactId: Чаще всего представляет собой название проекта.
Что такое Version: Версия проекта, можно указать просто 1.0 или v1.0, тут так-же как и с GroupId, без разницы.

1647375098051

Теперь нам предстоит изменить название главное класса на Main и указать версию майнкрафта для которой будет плагин (в нашем случае 1.18), для своего же удобства. По желанию можно указать авторов и описание. Если вы пропустите этот шаг, то позже в любом случае, вы сможете всё это изменить.
1647375429260

Укажите название папки в которую будет сохранён ваш проект и нажмите Finish.
1647375473335

𝟜 - Создание плагина

Теперь я представлю несколько вещей, которые будут являться примерами для разработки дальнейших плагинов. И конечно же, как всё это сделать, будет представлено в статье для общего понимания вещей;)

𝟭 - Форматированный (красивый) и удобный вывод цветных сообщений в консоль.
𝟮 - Выдача начального набора вещей при вызове команды.

Начнём с уже созданного нами до этого проекта:

1647377147494

Давайте создадим новый Package и назовём его utils для нашего же удобства и разместим там наш вспомогательный класс.
1647377278489

Создаём класс с простым названием Console
1647377375889


Выбираем обычное создание класса, не интерфейса и прочего.
1647377415060

Так-как данный класс является утилити-классом, то конструктор соответственно должен иметь модификатор private. Так-же укажем заранее некоторые поля, которые позже нам пригодятся.
Java:
package me.notch.demoplugin.utils;

import org.bukkit.Bukkit;
import org.bukkit.command.ConsoleCommandSender;

public class Console {

    private static final ConsoleCommandSender SENDER = Bukkit.getConsoleSender();
    private static final String PREFIX = "[DemoPlugin]";

    private Console() { }
}

Теперь нам необходимо создать метод отправки сообщений в консоль. Делается это довольно просто.
Java:
public static void log(String message) {
    SENDER.sendMessage(message);
}

Но, что если нам необходимо отправить составное сообщение? Которое состоит не только из строк, а например из чисел или объектов классов. Тут в дело приходят любимые generics. Однако метод sendMessage позволяет принимать в виде аргумента только строку, что тогда делать? Привести обратно к строке? Но каким образом? Тут нам спешит на помощь класс StringBuilder. С его помощью, мы сможем соединить все элементы массива (переданные ввиде аргументов объекты) в единую строку.
Java:
public static <T> void log(T[] messages) {
    StringBuilder builder = new StringBuilder(PREFIX);

    for (T msg : messages)
        builder.append(" ").append(msg);

    SENDER.sendMessage(builder.toString().trim() );
}

Однако, вот незадача, постоянно инициализировать перед этим массив из разно-типовых объектов неудобно, очень даже неудобно, поэтому мы будем использовать замечательные Variable Arguments. Они упростят нашу жизнь, я уверен в этом.. по крайней мере в этом году.. И давайте тогда вынесем всю сборку строки в один метод, чтобы всё смотрелось гармонично.
Java:
public static <T> void log(T... messages) {
    SENDER.sendMessage(compressArgs(messages) );
}

@SafeVarargs
private static <T> String compressArgs(T... args) {
    StringBuilder builder = new StringBuilder(PREFIX);

    for (T arg : args)
        builder.append(" ").append(arg);

    return builder.toString().trim();
}

Теперь нам стало скучно и мы бы хотели увидеть разноцветные сообщения в консоли, но как? Довольно таки просто, используем метод ChatColor#translateAlternateColorCodes. Теперь наш класс имеет вот такой код:
Java:
package me.notch.demoplugin.utils;

import net.md_5.bungee.api.ChatColor;
import org.bukkit.Bukkit;
import org.bukkit.command.ConsoleCommandSender;

public class Console {

    private static final ConsoleCommandSender SENDER = Bukkit.getConsoleSender();
    private static final String PREFIX = "[DemoPlugin]";

    private Console() { }

    @SafeVarargs
    public static <T> void log(T... messages) {
        SENDER.sendMessage(colored(compressArgs(messages) ) );
    }

    private static String colored(String message) {
        return ChatColor.translateAlternateColorCodes('&', message);
    }

    @SafeVarargs
    private static <T> String compressArgs(T... args) {
        StringBuilder builder = new StringBuilder(PREFIX);

        for (T arg : args)
            builder.append(" ").append(arg);

        return builder.toString().trim();
    }
}

Раз уж мы сделали этот класс, то давайте попробуем вывести несколько сообщений при включении плагина:
Java:
package me.notch.demoplugin;

import me.notch.demoplugin.utils.Console;
import org.bukkit.plugin.java.JavaPlugin;

import java.util.Date;

public final class Main extends JavaPlugin {

    @Override
    public void onEnable() {
        Console.log("&9Plugin's Author:", getDescription().getAuthors().get(0) );
        Console.log("&9Current date:", new Date(System.currentTimeMillis() ) );
    }

    @Override
    public void onDisable() {
        // Plugin shutdown logic
    }
}

Для того, чтобы собрать весь наш плагин в единый .jar пакет, нам необходимо нажать на функцию package в окне Maven
1647414541160

После этого в папке target мы сможем увидеть скомпилированный нами плагин:
1647414619481

Теперь приступим к созданию команды. Первоначально нам необходимо указать в файле plugin.yml название нашей команды, указать правильное использование/описание по желанию. Делаем это вот таким образом:
1647379321337

Теперь нам необходимо создать новый пакейдж commands и разместить там класс, который будет являться исполнителем команды. Вот такой класс получился у меня:
Java:
package me.notch.demoplugin.commands;

import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;

public class KitCommandExecutor implements CommandExecutor {
 
    @Override
    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
        return false;
    }
}

Давайте создадим единый список стартовых вещей и накидаем туда чего-нибудь. Это будет выглядеть примерно вот так:
Java:
private final static List<ItemStack> STARTER_KIT = new LinkedList<>();

static {
    // Броня
    ItemStack helmet = new ItemStack(Material.CHAINMAIL_HELMET); STARTER_KIT.add(helmet);
    ItemStack chestPlate = new ItemStack(Material.CHAINMAIL_CHESTPLATE); STARTER_KIT.add(chestPlate);
    ItemStack leggings = new ItemStack(Material.CHAINMAIL_LEGGINGS); STARTER_KIT.add(leggings);
    ItemStack boots = new ItemStack(Material.CHAINMAIL_BOOTS); STARTER_KIT.add(boots);
    // Инструменты
    ItemStack sword = new ItemStack(Material.IRON_SWORD); STARTER_KIT.add(sword);
    ItemStack pickaxe = new ItemStack(Material.IRON_PICKAXE); STARTER_KIT.add(pickaxe);
    ItemStack axe = new ItemStack(Material.IRON_AXE); STARTER_KIT.add(axe);
    ItemStack shovel = new ItemStack(Material.IRON_SHOVEL); STARTER_KIT.add(shovel);
    // Еда
    ItemStack apple = new ItemStack(Material.APPLE, 32); STARTER_KIT.add(apple);
    ItemStack pork = new ItemStack(Material.PORKCHOP, 32); STARTER_KIT.add(pork);
    // Предметы
    ItemStack oakWood = new ItemStack(Material.OAK_WOOD, 48); STARTER_KIT.add(oakWood);
    ItemStack glass = new ItemStack(Material.GLASS, 48); STARTER_KIT.add(glass);
}

Теперь при вызове команды нам необходимо проверить, что она вызвана не через консоль, в ином случае вывести ошибку. Так-же скопируем все предметы которые были добавлены в стартовый набор и присвоим им название, что предмет принадлежит определённому игроку. Конечный код будет выглядеть следующим образом:
Java:
package me.notch.demoplugin.commands;

import me.notch.demoplugin.utils.Console;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;

import java.util.LinkedList;
import java.util.List;

public class KitCommandExecutor implements CommandExecutor {

    private final static List<ItemStack> STARTER_KIT = new LinkedList<>();

    static {
        // Броня
        ItemStack helmet = new ItemStack(Material.CHAINMAIL_HELMET); STARTER_KIT.add(helmet);
        ItemStack chestPlate = new ItemStack(Material.CHAINMAIL_CHESTPLATE); STARTER_KIT.add(chestPlate);
        ItemStack leggings = new ItemStack(Material.CHAINMAIL_LEGGINGS); STARTER_KIT.add(leggings);
        ItemStack boots = new ItemStack(Material.CHAINMAIL_BOOTS); STARTER_KIT.add(boots);
        // Инструменты
        ItemStack sword = new ItemStack(Material.IRON_SWORD); STARTER_KIT.add(sword);
        ItemStack pickaxe = new ItemStack(Material.IRON_PICKAXE); STARTER_KIT.add(pickaxe);
        ItemStack axe = new ItemStack(Material.IRON_AXE); STARTER_KIT.add(axe);
        ItemStack shovel = new ItemStack(Material.IRON_SHOVEL); STARTER_KIT.add(shovel);
        // Еда
        ItemStack apple = new ItemStack(Material.APPLE, 32); STARTER_KIT.add(apple);
        ItemStack pork = new ItemStack(Material.PORKCHOP, 32); STARTER_KIT.add(pork);
        // Предметы
        ItemStack oakWood = new ItemStack(Material.OAK_WOOD, 48); STARTER_KIT.add(oakWood);
        ItemStack glass = new ItemStack(Material.GLASS, 48); STARTER_KIT.add(glass);
    }


    @Override
    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
        if (!(sender instanceof Player p)) {
            Console.log("&4Console cannot use this command!");
            return true;
        }

        if (args.length > 0) {
            // Смотрим какой набор хочет получить человек
            if (args[0].equalsIgnoreCase("starter") || args[0].equalsIgnoreCase("start") ) {
                List<ItemStack> copied = new LinkedList<>(STARTER_KIT);

                for (ItemStack item : copied) {
                    ItemMeta meta = item.getItemMeta();
                    meta.setDisplayName(
                            ChatColor.translateAlternateColorCodes('&',
                                    "&dПринадлежит игроку &c" + p.getName())
                    );
                    item.setItemMeta(meta);
                }

                p.getInventory().addItem(copied.toArray(ItemStack[]::new));
            } else {
                // В ином случае выводим ошибку
                p.sendMessage(ChatColor.
                        translateAlternateColorCodes('&',"&cТакого набора не существует!") );
            }
        }
        return true;
    }
}

Нам так-же необходимо зарегистрировать команду на сервере, это делается следующим образом:
Java:
package me.notch.demoplugin;

import me.notch.demoplugin.commands.KitCommandExecutor;
import me.notch.demoplugin.utils.Console;
import org.bukkit.plugin.java.JavaPlugin;

import java.util.Date;

public final class Main extends JavaPlugin {

    @Override
    public void onEnable() {
        Console.log("&9Plugin's Author:", getDescription().getAuthors().get(0) );
        Console.log("&9Current date:", new Date(System.currentTimeMillis() ) );

        getCommand("kit").setExecutor(new KitCommandExecutor() );
    }

    @Override
    public void onDisable() {
        // Plugin shutdown logic
    }
}

Теперь при вызове команды /kit starter или /kit start нам будет выдаваться именной набор вещей.



ЗАКЛЮЧЕНИЕ
* * *
В заключение, хочу сказать, что я старался расписать, как можно больше в плане объяснений тех или иных моментов по написанию кода. Признаю, не хватает опыта в написании таких статей, но не судите слишком строго, я попытался - я сделал. И считаю что сделал довольно не плохо, если будет много запросов по наиболее детализированному объяснению кода, то я сделаю несколько апдейтов в этой же статье.
Так-же в дальнейшем, в этом же разделе, буду постить некоторые гайды по созданию интересных плагинов, с полным код и объяснениями. Хочу так-же упомянуть, то что писалось в самом начале: я категорически не собираюсь разъяснять те или иные синтаксические моменты языка программирования, это уже должно быть в понимании человека, который собирается писать плагины, другого выбора быть не может.
Отдельное спасибо тем, кто дочитал с начало до самого конца - вы лучшие 🆒 Успехов вам всем в ваших начинаниях!

Материалы, которые использовались в статье:
ЯП Java - Spigot - ЯП Форки - Open Source Project - Eclipse - NetBeans - IntelliJ IDEA - Java Generics - Java Varargs -
Подключенные зависимости файла pom.xml:

Код:
<dependencies>
    <dependency>
        <groupId>org.spigotmc</groupId>
        <artifactId>spigot-api</artifactId>
        <version>1.18-R0.1-SNAPSHOT</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.jetbrains</groupId>
        <artifactId>annotations</artifactId>
        <version>23.0.0</version>
        <scope>provided</scope>
    </dependency>
</dependencies>
 

Вложения

  • 1647332068024.png
    1647332068024.png
    9,8 КБ · Просмотры: 46
  • 1647332186376.png
    1647332186376.png
    28,3 КБ · Просмотры: 22
  • 1647374275208.png
    1647374275208.png
    28,4 КБ · Просмотры: 16
  • 1647374349929.png
    1647374349929.png
    91,4 КБ · Просмотры: 14
  • 1647374514545.png
    1647374514545.png
    61,5 КБ · Просмотры: 12
  • 1647375364902.png
    1647375364902.png
    18,2 КБ · Просмотры: 14
  • 1647377037179.png
    1647377037179.png
    127,6 КБ · Просмотры: 20
Последнее редактирование:
ВерхНиз