Войти или зарегистрироваться
  • Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.

Использование craftbukkit в качестве библиотеки потребует перекомпиляции проекта после обновлений

Используете ли вы классы из пакетов: net.minecraft.server и org.bukkit.craftbukkit?


  • Опрос закрыт .

fromgate

Старожил
Пользователь
Баллы
173
Имя в Minecraft
fromgate
Добрый день!

Любопытное обновление, произошло неделю назад:
https://github.com/Bukkit/CraftBukkit/commit/8f12382e8efc8c39a919af9180dd884caf3720ff

Пояснение EvilSeph по этому поводу:
https://github.com/Bukkit/CraftBukk...919af9180dd884caf3720ff#commitcomment-2277397

Кратко. Будущие версии craftbukkit будут содержать пакеты в названия которых будет включаться версия craftbukkit и minecraft.
То есть, например, вы используете класс org.bukkit.craftbukkit.entity.CraftPlayer с учетом этого обновления он будет называться, допустим org.bukkit.craftbukkit.1-4-5-r01.entity.CraftPlayer
Соответственно после выхода обновленного craftbukkit'а он будет называться уже org.bukkit.craftbukkit.1-4-5-r02.entity.CraftPlayer и плагин автоматически перестает работать.

Чем это плохо:
1. после каждого обновления надо будет обновлять плагины. Мне потребовалось изменять какой-то плагин при выходе 1.4 из-за того, что что-то поменялось в коде craftbukkit. Но при этом, он нормально себя чувствовал без всяких перекомпиляций начиная со времен 1.2.х. Т.е. он нормально пережил обновления: 1.2.3, 1.2.4, 1.2.5, 1.3.1, 1.3.2 и потребовал внимания только при 1.4.2 и теперь нормально работает, под 1.4.5. Теперь же мне при каждом выходе надо будет создавать новую версию. Это будет утомительно :(
2. Однозначно увеличится время на одобрение плагинов: представьте, что помимо обычных плагинов в очередь будет попадать и огромная куча перекомплированных плагинов.
3. Возникнут проблемы при обновлениях серверов: надо будет ждать обновления ещё большего числа плагинов.

Чем это хорошо:
1. Повышается безопасность серверов, миров и т.п.
2. Повышается активность разработчиков: больше вероятности, что они вовремя заметят, что в craftbukkit или что-то изменилось и своевременно сделают обновление.
3. Ну и в конце-концов я это воспринимаю как один из признаков того, что Mojang всерьёз взялись за API: такие мысли в голову EvilSeph просто так не приходят, наверняка такое ограничение будет и в PluginAPI :)
4. Таких плагинов всего-то 10%

Примечение: всё выше сказанное не относится к плагинам использующим только лишь Bukkit API (т.е. в качестве внешней библиотеки подключается только bukkit.jar)
 
Весьма печальная новость.
То есть, если я использую net.minecraft.server, то придется писать под каждую версию сервера отдельный плагин?
:(:(:(:(:(
Попробую выкрутиться, например через массив имен классов, рефлексии и класслоадер эмулировать режим совместимости (это костыли, но я так уже делал :p. Рефлексии никак не отражаются на быстродействии, если нужные классы и методы загрузить в память заранее.)
 
Ну я так понимаю, в большинстве случаев, достаточно будет перекомпилировать с новой "библиотекой". Если пользоваться dev.bukkit.org в качестве хранилища - то вобщем-то этого будет достаточно: старые версии под старые craftbukkit там будут доступны — кому надо, тот возьмет; а последняя версия будет всегда привязана к последнему баккиту и это не так страшно.
 
Ну я так понимаю, в большинстве случаев, достаточно будет перекомпилировать с новой "библиотекой".
В новой библиотеке перекомпилировать проект не получится, если он использует craftbukkit.
Придется изменять имена классов в импорте.
С другой стороны, если изменить - все отлично скомпилируется, но только для этой версии.
Таким образом новая версия крафтбукита == новый плагин. (если ничего не придумать)
Похоже на хитрое ограничение, чтоб разработчики старались использовать только bukkit API.

С другой стороны Bukkit начинает радовать:
Add EntityEquipment API
Add isSolid() to Material
Add FurnaceExtractEvent
Add API to get and set collar colors of wolves
но этого все равно не достаточно (и должно было произойти как минимум месяц назад! API для книжек до сих пор не ввели).

UPD:
И будет в скором времени какой-нибудь плагин, расширения API, типа Vault или ProtocolLib
 
Аааа, ясно теперь почему у меня на 1.4.5 все плагины полетели(
 
Если щас одобрение версии плагина на деве занимает минимум 2 дня... Так тут нужно будет обновить 20% плагинов каждую версию.. Это чтож теперь, неделю ждать?
 
Они еще ничего не изменили.
Следите за обновлениями на гитхабе.

Есть уже. Сейчас с дуру поставил себе последний девбилд и тут же получил:
Java:
2012-12-12 21:47:15 [INFO] [CameraObscura] Enabling CameraObscura v0.0.1
2012-12-12 21:47:16 [SEVERE] Error occurred while enabling CameraObscura v0.0.1 (Is it up to date?)
java.lang.NoClassDefFoundError: org/bukkit/craftbukkit/inventory/CraftItemStack
    at fromgate.obscura.Obscura.onEnable(Obscura.java:105)
    at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:217)
    at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:374)
    at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:381)
    at org.bukkit.craftbukkit.v1_4_5.CraftServer.loadPlugin(CraftServer.java:270)
    at org.bukkit.craftbukkit.v1_4_5.CraftServer.enablePlugins(CraftServer.java:252)
    at net.minecraft.server.v1_4_5.MinecraftServer.j(MinecraftServer.java:320)
    at net.minecraft.server.v1_4_5.MinecraftServer.e(MinecraftServer.java:299)
    at net.minecraft.server.v1_4_5.MinecraftServer.a(MinecraftServer.java:258)
    at net.minecraft.server.v1_4_5.DedicatedServer.init(DedicatedServer.java:147)
    at net.minecraft.server.v1_4_5.MinecraftServer.run(MinecraftServer.java:398)
    at net.minecraft.server.v1_4_5.ThreadServerApplication.run(SourceFile:856)
Caused by: java.lang.ClassNotFoundException: org.bukkit.craft*********ventory.CraftItemStack
    at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:34)
    at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:29)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 12 more

Ладно, мне не жалко. Но у меня на тестовом сервере (на котором по определению стоит минимум плагинов) не заработали:
VoxelSniper
NoSmoking
FakePlayersOnline
AdminCmd
Citizens
WorldGuard
WeatherMan

Мерзкое ощущение. Самое неприятное, что к примеру мне нужно банально менять наименование предмета. Но без craftbukkit в качестве библиотеки этого не сделаешь. Тьфу.
 
Есть уже. Сейчас с дуру поставил себе последний девбилд и тут же получил:
Java:
2012-12-12 21:47:15 [INFO] [CameraObscura] Enabling CameraObscura v0.0.1
2012-12-12 21:47:16 [SEVERE] Error occurred while enabling CameraObscura v0.0.1 (Is it up to date?)
java.lang.NoClassDefFoundError: org/bukkit/craftbukkit/inventory/CraftItemStack
    at fromgate.obscura.Obscura.onEnable(Obscura.java:105)
    at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:217)
    at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:374)
    at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:381)
    at org.bukkit.craftbukkit.v1_4_5.CraftServer.loadPlugin(CraftServer.java:270)
    at org.bukkit.craftbukkit.v1_4_5.CraftServer.enablePlugins(CraftServer.java:252)
    at net.minecraft.server.v1_4_5.MinecraftServer.j(MinecraftServer.java:320)
    at net.minecraft.server.v1_4_5.MinecraftServer.e(MinecraftServer.java:299)
    at net.minecraft.server.v1_4_5.MinecraftServer.a(MinecraftServer.java:258)
    at net.minecraft.server.v1_4_5.DedicatedServer.init(DedicatedServer.java:147)
    at net.minecraft.server.v1_4_5.MinecraftServer.run(MinecraftServer.java:398)
    at net.minecraft.server.v1_4_5.ThreadServerApplication.run(SourceFile:856)
Caused by: java.lang.ClassNotFoundException: org.bukkit.craft*********ventory.CraftItemStack
    at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:34)
    at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:29)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 12 more

Ладно, мне не жалко. Но у меня на тестовом сервере (на котором по определению стоит минимум плагинов) не заработали:
VoxelSniper
NoSmoking
FakePlayersOnline
AdminCmd
Citizens
WorldGuard
WeatherMan

Мерзкое ощущение. Самое неприятное, что к примеру мне нужно банально менять наименование предмета. Но без craftbukkit в качестве библиотеки этого не сделаешь. Тьфу.
Dev версии WG уже работают с последними билдами.
 
Есть уже. Сейчас с дуру поставил себе последний девбилд и тут же получил:
Java:
2012-12-12 21:47:15 [INFO] [CameraObscura] Enabling CameraObscura v0.0.1
2012-12-12 21:47:16 [SEVERE] Error occurred while enabling CameraObscura v0.0.1 (Is it up to date?)
java.lang.NoClassDefFoundError: org/bukkit/craftbukkit/inventory/CraftItemStack
    at fromgate.obscura.Obscura.onEnable(Obscura.java:105)
    at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:217)
    at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:374)
    at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:381)
    at org.bukkit.craftbukkit.v1_4_5.CraftServer.loadPlugin(CraftServer.java:270)
    at org.bukkit.craftbukkit.v1_4_5.CraftServer.enablePlugins(CraftServer.java:252)
    at net.minecraft.server.v1_4_5.MinecraftServer.j(MinecraftServer.java:320)
    at net.minecraft.server.v1_4_5.MinecraftServer.e(MinecraftServer.java:299)
    at net.minecraft.server.v1_4_5.MinecraftServer.a(MinecraftServer.java:258)
    at net.minecraft.server.v1_4_5.DedicatedServer.init(DedicatedServer.java:147)
    at net.minecraft.server.v1_4_5.MinecraftServer.run(MinecraftServer.java:398)
    at net.minecraft.server.v1_4_5.ThreadServerApplication.run(SourceFile:856)
Caused by: java.lang.ClassNotFoundException: org.bukkit.craft*********ventory.CraftItemStack
    at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:34)
    at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:29)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 12 more

Ладно, мне не жалко. Но у меня на тестовом сервере (на котором по определению стоит минимум плагинов) не заработали:
VoxelSniper
NoSmoking
FakePlayersOnline
AdminCmd
Citizens
WorldGuard
WeatherMan

Мерзкое ощущение. Самое неприятное, что к примеру мне нужно банально менять наименование предмета. Но без craftbukkit в качестве библиотеки этого не сделаешь. Тьфу.
Угу, такая же хрень:(
 
Dev версии WG уже работают с последними билдами.
Да понятно, что все будут поддерживать рано или поздно. Вообще мне похоже придётся для своих плагинов сделать костыль, который будет отключать ряд функций при отсутствии нужного класса. Т.е. к примеру, тот же WeatherMan будет работать как надо, но не будет принудительно сохранять чанки. Это приведет к тому, что после апдейта баккита WeatherMan работать не перестанет, но при замене биомов на больших площадях не все чанки будут сохранять смену биомов (спасибо craftbukkit team за игнорирование баг-репортов).
Точно также для плагина, который я пишу сейчас - там у меня есть элемент - смена названия предмета. Эта функция будет отключаться при смене версии craftbukkit.jar.
Если бы они хотя бы быстро реализовывали предложения игроков и фиксили баги - тогда такой шаг был бы оправданным. Пока же.. это чистой воды издевательство :(
 
Вроде spigot фиксят эту штучку с 322 билда.
Плагины 1.4.5 r0.3 на 322 билде будут работать.
Иду тестировать...
 
Вроде spigot фиксят эту штучку с 322 билда.
Плагины 1.4.5 r0.3 на 322 билде будут работать.
Иду тестировать...
Тест прошел успешно.
Большинство плагинов работает.
Не работает: WorldGuard
Тест будет проверятся мной, список работающих и неработающих плагинов будет пополнятся.
 
Тест №2 прошел успешно.
Большинство плагинов работает.
Из них: xAuth,WorldEdit,WorldBorder,AutoMessage,AntiShare,iConomy,iChat,HideStream,Essentials,MobArena,Scavenger,ChestShop,LWC,ruFix,Orebfuscator,PerformanceMonitor,Jobs...
Не работает: WorldGuard,WGFixb.xd,LokiColor, NoCheatPlus...
Список будет пополнятся.
 
Эх... как же это бесит!
Я нашел способ наеобмануть класслоадер с помощью прокси и рефлексий.
Для мсье, знающих толк в извращениях.
Инструкция:

Создаем класс, который будет оперировать с объектами CraftBukkit:
Java:
/*
Прошу прощения за имена классов и методов, но имхо они отражают всю суть последних обновлений CraftBukkit
*/
public class VersionFucker {
    static String version = "";
    static boolean fuck = false;
 
    static class FuckHandler implements InvocationHandler{
        private Object o;
        public FuckHandler(Object o){this.o=o;}
        @Override  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Method m = o.getClass().getDeclaredMethod(method.getName(),method.getParameterTypes());
            return m.invoke(o, args);
        }
    }
 
    static {
        try {
            Object s = Bukkit.getServer();
            Method m = s.getClass().getDeclaredMethod("getHandle");
            Object cs = m.invoke(s);
            String className = cs.getClass().getName();
            String[] vers = className.split("\\.");
            if (vers.length == 5) {
                fuck = true;
                version = vers[3] + ".";
            }
        } catch (Throwable ignored) {
        }
    }
 
    public static boolean needFuck() {
        return fuck;
    }
 
    public static <T> T fuckNew(String className, Class<T> proxy, Class[] types, Object... params) {
        try {
            Class clazz = Class.forName(fixClassName(className));
            Constructor constructor = clazz.getDeclaredConstructor(types);
            Object ob = constructor.newInstance(params);
            return fuck(proxy,ob);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
 
    public static <T> T fuck(Class<T> proxy, final Object object) {
        try {
            return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{proxy}, new FuckHandler(object));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
 
    private static String fixClassName(String className) {
        className = className.replace("org.bukkit.craftbukkit.", "org.bukkit.craftbukkit." + version);
        className = className.replace("net.minecraft.server.", "net.minecraft.server." + version);
        return className;
    }
}
Теперь допустим, нам нужно создать new CraftItemStack(15)
1) создаем прокси-интерфейс, в который копируем необходимые методы из CraftItemStack:
Java:
interface VarItemStack {
    Material getType();
}
2) создаем объект таким образом:
Java:
VarItemStack stack = VersionFucker.fuckNew("org.bukkit.craft*********ventory.CraftItemStack",VarItemStack.class,new Class[]{int.class},15);
где параметры функции:
1 - полное имя класса для старых версий CraftBukkit​
2 - наш прокси-интерфейс​
3 - массив классов входных значений оригинального конструктора. Т.е. мы должны были бы вызвать new CraftItemStack(15), где один входной параметр типа int. Поэтому здесь должен быть массив из одного класса: new Class[]{int.class}​
4 и далее - входные параметры.​
3) используем наш объект как хотим. Например, так:
Java:
System.out.print(stack.getType());

Другой вариант:
Например у нас уже есть объект stack типа CraftItemStack, но хотим использовать его без импорта класса.
Java:
Object stack;
Чтобы использовать его методы, делаем так:
Java:
VarItemStack myStack = VersionFucker.fuck(VarItemStack.class,stack);
где параметры функции:
1 - наш прокси-интерфейс​
2 - наш объект​
теперь можем в полной мере пользоваться его методами:
Java:
System.out.print(myStack .getType());

Должно работать на всех версиях, с измененными названиями пакетов и оригинальными. Я проверял на v1_4_5 всего для нескольких типов объектов.
Не тестировал для net.minecraft.server, но тоже должно работать.

Это не является полноценным методом портирования плагина на все версии CraftBukkit (по большей части - костыль), но если использование CraftBukkit требуется отчасти и не во многих местах - он вполне подойдет.
 
DPOH-VAR, застрелиться! Вчера тоже размышлял как бы обойти, но такое точно бы "не родил". Обязательно попробую. Если получится, то будет отлично. Будем дружно смеяться на буккитом.
 
Вроде spigot фиксят эту штучку с 322 билда.
Плагины 1.4.5 r0.3 на 322 билде будут работать.
Иду тестировать...

А плагино 1.4.5-r0.2 на нем будут работать? Если нет, то это не фикс, а тоже самое.
 
А плагино 1.4.5-r0.2 на нем будут работать? Если нет, то это не фикс, а тоже самое.
Я это написал полчаса назад и сразу выложил. Не было времени проверять на старой сборке.
Работать должно с обычными и переименованными пакетами, т.е. на любой версии.
Если вдруг откажется работать с r0.2 и старше - то я просто исравлю баг ;).

ПС: там происходит подмена имени класса объекта, основываясь на имени класса случайно взятого объекта из крафтбуккита (для упрощения я взял CraftServer). Если там присутствует лишний пакет (тот самый v1_4_5) - факер его запоминает и в будущем приписывает всем классам. Если пакета с версией не оказалось - приписка будет пустая.
 

Поделиться этой страницей

Назад
Верх