- Баллы
- 76
- Имя в Minecraft
- SiRiuS_OSiRiuS
Оригинал (EN)
Я видел много людей, которые делают плагины, которые зависят от версии. Они, например, отправляют сообщения в title или actionbar. Многие используют код NMS (net.minecraft.server), чтобы использовать эти возможности, так как это единственный способ. Так как NMS представляет конкретную версию, я видел немало плагинов, которые зависят от версии, и когда выходит обновление, они больше не работают с предыдущими версиями.
Недавно я искал лучший способ предложить поддержку нескольких версий, в зависимости от версии сервера, на котором работал мой плагин. Я остановился на Рефлексии.
Пока я думал, что это - классная вещь (т.к. мой плагин теперь поддерживает предыдущие версии), @DarkSeraphim в теме, где я разместил способ с рефлексией, что он очень сильно нагружает сервер, и правильнее было бы использовать интерфейс, который позволит мне всего лишь проверять, какую совместимость мне нужно предложить, когда мой плагин запущен.
Использование интерфейса позволяет моему коду с NMS находиться в различных классах, при этом будет загружен и использован только соответствующий с версией сервера. Это избавляет от необходимости использовать рефлексию!
Несмотря на то, что этот гайд не избавляет от необходимости использовать рефлексию где бы вы ни захотели (бывают причины, когда вам НУЖНО использовать её), для таких вещей, как отправка сообщений в title или actionbar он отлично подходит!
В этом примере мы будем отправлять сообщение в actionbar игроку, зашедшему на сервер. Этот плагин будет работать на версиях 1.8.x.
Итак, начнём:
В своём плагине создайте отдельный пакет для вашего интерфейса и NMS-классов:
Внутри этого пакета мы создадим интерфейс под названием Actionbar.
Этот интерфейс будет хранить абстрактный метод, который будут использовать наши NMS-классы для отправки в actionbar.
Любой класс, который реализует наш интерфейс, должен содержать его абстрактный метод.
Таким образом, мы сможем хранить Actionbar в нашем главном классе, но при этом можем присваивать туда любой из наших NMS-классов, который реализуют интерфейс.
Довольно просто, правда? Здесь всего лишь одна строка кода.
Это абстрактный метод, который будут использовать наши классы, что реализуют Actionbar, для вызова методов конкретной версии NMS.
Если вы использовали это для того, чтобы сделать что-то помимо отправки сообщения, вы можете добавить столько методов, сколько вам необходимо для каждого NMS-класса. Учтите, что каждый класс, который реализует этот интерфейс, должен содержать каждый метод, описанный вами здесь.
Теперь у нас есть наш интерфейс, давайте создадим наши классы, которые реализуют его и отправляют текст в actionbar игроков при помощи NMS!
Класс 1.8.1, реализующий наш интерфейс Actionbar:
Класс 1.8.3, реализующий наш интерфейс Actionbar:
Теперь нам осталось лишь создать наш главный класс!
В этот туториале я хранил всё в главном классе плагина.
Если у вас большой плагин, и вы используете несколько классов (класс для слушателей, например)
вам следует создать геттер для Actionbar в своём главном классе, таким образом другие ваши классы смогут обращаться к нему.
Создать геттер - очень просто, и вы должны уже знать, как, если вы смотрите этот туториал.
Теперь все ваши классы имеют доступ к отправке сообщения в actionbar!
Есть ещё много способов проверить версию сервера. Я использовал название пакета сервера bukkit, но вы также можете использовать Bukkit.getBukkitVersion() и проверять/присваивать ваш NMS-класс в зависимости от этого.
Если вы инициализируете один из ваших NMS-классов, который не подходит версии сервера, ваш плагин выбросит ClassNotFoundException.
Убедитесь, что вы инициализируете только класс для конкретной версии сервера, на котором работает плагин!
Я видел много людей, которые делают плагины, которые зависят от версии. Они, например, отправляют сообщения в title или actionbar. Многие используют код NMS (net.minecraft.server), чтобы использовать эти возможности, так как это единственный способ. Так как NMS представляет конкретную версию, я видел немало плагинов, которые зависят от версии, и когда выходит обновление, они больше не работают с предыдущими версиями.
Недавно я искал лучший способ предложить поддержку нескольких версий, в зависимости от версии сервера, на котором работал мой плагин. Я остановился на Рефлексии.
Пока я думал, что это - классная вещь (т.к. мой плагин теперь поддерживает предыдущие версии), @DarkSeraphim в теме, где я разместил способ с рефлексией, что он очень сильно нагружает сервер, и правильнее было бы использовать интерфейс, который позволит мне всего лишь проверять, какую совместимость мне нужно предложить, когда мой плагин запущен.
Использование интерфейса позволяет моему коду с NMS находиться в различных классах, при этом будет загружен и использован только соответствующий с версией сервера. Это избавляет от необходимости использовать рефлексию!
Несмотря на то, что этот гайд не избавляет от необходимости использовать рефлексию где бы вы ни захотели (бывают причины, когда вам НУЖНО использовать её), для таких вещей, как отправка сообщений в title или actionbar он отлично подходит!
В этом примере мы будем отправлять сообщение в actionbar игроку, зашедшему на сервер. Этот плагин будет работать на версиях 1.8.x.
Итак, начнём:
В своём плагине создайте отдельный пакет для вашего интерфейса и NMS-классов:
Внутри этого пакета мы создадим интерфейс под названием Actionbar.
Этот интерфейс будет хранить абстрактный метод, который будут использовать наши NMS-классы для отправки в actionbar.
Любой класс, который реализует наш интерфейс, должен содержать его абстрактный метод.
Таким образом, мы сможем хранить Actionbar в нашем главном классе, но при этом можем присваивать туда любой из наших NMS-классов, который реализуют интерфейс.
Код:
package me.clip.actionbarplugin.actionbar;
import org.bukkit.entity.Player;
public interface Actionbar {
public void sendActionbar(Player p, String message);
}
Это абстрактный метод, который будут использовать наши классы, что реализуют Actionbar, для вызова методов конкретной версии NMS.
Если вы использовали это для того, чтобы сделать что-то помимо отправки сообщения, вы можете добавить столько методов, сколько вам необходимо для каждого NMS-класса. Учтите, что каждый класс, который реализует этот интерфейс, должен содержать каждый метод, описанный вами здесь.
Теперь у нас есть наш интерфейс, давайте создадим наши классы, которые реализуют его и отправляют текст в actionbar игроков при помощи NMS!
Класс 1.8.1, реализующий наш интерфейс Actionbar:
Код:
package me.clip.actionbarplugin.actionbar;
import net.minecraft.server.v1_8_R1.ChatSerializer;
import net.minecraft.server.v1_8_R1.IChatBaseComponent;
import net.minecraft.server.v1_8_R1.PacketPlayOutChat;
import org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
public class Actionbar_1_8_R1 implements Actionbar {
@Override
public void sendActionbar(Player p, String message) {
IChatBaseComponent icbc = ChatSerializer.a("{\"text\": \"" + message + "\"}");
PacketPlayOutChat bar = new PacketPlayOutChat(icbc, (byte) 2);
((CraftPlayer) p).getHandle().playerConnection.sendPacket(bar);
}
}
Класс 1.8.3, реализующий наш интерфейс Actionbar:
Код:
package me.clip.actionbarplugin.actionbar;
import net.minecraft.server.v1_8_R2.IChatBaseComponent;
import net.minecraft.server.v1_8_R2.PacketPlayOutChat;
import net.minecraft.server.v1_8_R2.IChatBaseComponent.ChatSerializer;
import org.bukkit.craftbukkit.v1_8_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
public class Actionbar_1_8_R2 implements Actionbar {
@Override
public void sendActionbar(Player p, String message) {
IChatBaseComponent icbc = ChatSerializer.a("{\"text\": \"" + message + "\"}");
PacketPlayOutChat bar = new PacketPlayOutChat(icbc, (byte) 2);
((CraftPlayer) p).getHandle().playerConnection.sendPacket(bar);
}
}
Код:
package me.clip.actionbarplugin;
import me.clip.actionbarplugin.actionbar.Actionbar;
import me.clip.actionbarplugin.actionbar.Actionbar_1_8_R1;
import me.clip.actionbarplugin.actionbar.Actionbar_1_8_R2;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;
public class ActionbarPlugin extends JavaPlugin implements Listener {
// наш интерфейс! Любой класс, что реализует Actionbar, может быть присвоен сюда!
// когда нам понадобится отправить текст в actionbar, нам всего лишь нужно будет вызвать actionbar.sendActionbar(player, message);
// когда соответствующий NMS-класс будет присвоен в методе onEnable, мы будем совместимы с предыдущими версиями!
private Actionbar actionbar;
@Override
public void onEnable() {
if (setupActionbar()) {
Bukkit.getPluginManager().registerEvents(this, this);
getLogger().info("Установка Actionbar успешна!");
getLogger().info("Процесс установки плагина завершён!");
} else {
getLogger().severe("Не удалось установить Actionbar!");
getLogger().severe("Ваш сервер несовместим с этим плагином!");
Bukkit.getPluginManager().disablePlugin(this);
}
}
// этот метод установит наш actionbar и вернёт true, если сервер работает на
// совместимой с нашими NMS-классами версии.
// Если сервер несовместим, вернётся false!
private boolean setupActionbar() {
String version;
try {
version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
} catch (ArrayIndexOutOfBoundsException whatVersionAreYouUsingException) {
return false;
}
getLogger().info("Ваш сервер использует версию " + version);
if (version.equals("v1_8_R1")) {
//сервер работает на 1.8-1.8.1, поэтому нам нужно использовать NMS-класс 1.8 R1
actionbar = new Actionbar_1_8_R1();
} else if (version.equals("v1_8_R2")) {
//сервер работает на 1.8.3, поэтому нам нужно использовать NMS-класс 1.8 R2
actionbar = new Actionbar_1_8_R2();
}
// Вернётся true, если версия сервера оказалось совместимой с версией одного из наших NMS-классов,
// потому что если так и есть, наш actionbar не будет null
return actionbar != null;
}
@EventHandler
public void onJoin(PlayerJoinEvent event) {
actionbar.sendActionbar(event.getPlayer(), "Welcome to the server!");
}
}
В этот туториале я хранил всё в главном классе плагина.
Если у вас большой плагин, и вы используете несколько классов (класс для слушателей, например)
вам следует создать геттер для Actionbar в своём главном классе, таким образом другие ваши классы смогут обращаться к нему.
Создать геттер - очень просто, и вы должны уже знать, как, если вы смотрите этот туториал.
Код:
public Actionbar getActionbar() {
return actionbar;
}
Есть ещё много способов проверить версию сервера. Я использовал название пакета сервера bukkit, но вы также можете использовать Bukkit.getBukkitVersion() и проверять/присваивать ваш NMS-класс в зависимости от этого.
Если вы инициализируете один из ваших NMS-классов, который не подходит версии сервера, ваш плагин выбросит ClassNotFoundException.
Убедитесь, что вы инициализируете только класс для конкретной версии сервера, на котором работает плагин!
. Иди спи дальше со своим екшен баром и тайтлом.