1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
  2. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

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

Тема в разделе "Разработка плагинов для новичков", создана пользователем fromgate, 11 дек 2012.

?

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

Голосование закрыто 21 дек 2012.
  1. Да, всегда

    16,7%
  2. Да, но редко

    26,7%
  3. Нет, только Bukkit API

    23,3%
  4. Нет, а что это?

    33,3%
  1. Автор темы
    fromgate

    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)
     
    Игнорекс, ITrAnEI, Alastar и 4 другим нравится это.
  2. DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    Весьма печальная новость.
    То есть, если я использую net.minecraft.server, то придется писать под каждую версию сервера отдельный плагин?
    :(:(:(:(:(
    Попробую выкрутиться, например через массив имен классов, рефлексии и класслоадер эмулировать режим совместимости (это костыли, но я так уже делал :p. Рефлексии никак не отражаются на быстродействии, если нужные классы и методы загрузить в память заранее.)
     
    ITrAnEI нравится это.
  3. Автор темы
    fromgate

    fromgate Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    fromgate
    Ну я так понимаю, в большинстве случаев, достаточно будет перекомпилировать с новой "библиотекой". Если пользоваться dev.bukkit.org в качестве хранилища - то вобщем-то этого будет достаточно: старые версии под старые craftbukkit там будут доступны — кому надо, тот возьмет; а последняя версия будет всегда привязана к последнему баккиту и это не так страшно.
     
  4. DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    В новой библиотеке перекомпилировать проект не получится, если он использует 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
     
    ITrAnEI нравится это.
  5. Alastar

    Alastar Старожил Пользователь

    Баллы:
    173
    Аааа, ясно теперь почему у меня на 1.4.5 все плагины полетели(
     
    blogger2 нравится это.
  6. Jampire

    Jampire Старожил Пользователь

    Баллы:
    173
    Skype:
    jampire-h
    Имя в Minecraft:
    Jampire
    Если щас одобрение версии плагина на деве занимает минимум 2 дня... Так тут нужно будет обновить 20% плагинов каждую версию.. Это чтож теперь, неделю ждать?
     
    GJEvolution нравится это.
  7. DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    Они еще ничего не изменили.
    Следите за обновлениями на гитхабе.
     
  8. Автор темы
    fromgate

    fromgate Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    fromgate
    Есть уже. Сейчас с дуру поставил себе последний девбилд и тут же получил:
    Код:
    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 в качестве библиотеки этого не сделаешь. Тьфу.
     
    ITrAnEI нравится это.
  9. Автор темы
    fromgate

    fromgate Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    fromgate
    ITrAnEI нравится это.
  10. Автор темы
    fromgate

    fromgate Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    fromgate
    ITrAnEI и Linkinkov нравится это.
  11. Linkinkov

    Linkinkov Старожил Пользователь

    Баллы:
    173
    Skype:
    linkinkov1
    Имя в Minecraft:
    linkinkov
    Dev версии WG уже работают с последними билдами.
     
    ITrAnEI нравится это.
  12. Alastar

    Alastar Старожил Пользователь

    Баллы:
    173
    Угу, такая же хрень:(
     
  13. Автор темы
    fromgate

    fromgate Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    fromgate
    Да понятно, что все будут поддерживать рано или поздно. Вообще мне похоже придётся для своих плагинов сделать костыль, который будет отключать ряд функций при отсутствии нужного класса. Т.е. к примеру, тот же WeatherMan будет работать как надо, но не будет принудительно сохранять чанки. Это приведет к тому, что после апдейта баккита WeatherMan работать не перестанет, но при замене биомов на больших площадях не все чанки будут сохранять смену биомов (спасибо craftbukkit team за игнорирование баг-репортов).
    Точно также для плагина, который я пишу сейчас - там у меня есть элемент - смена названия предмета. Эта функция будет отключаться при смене версии craftbukkit.jar.
    Если бы они хотя бы быстро реализовывали предложения игроков и фиксили баги - тогда такой шаг был бы оправданным. Пока же.. это чистой воды издевательство :(
     
    ITrAnEI нравится это.
  14. MySt1k

    MySt1k Старожил Пользователь

    Баллы:
    173
    Вроде spigot фиксят эту штучку с 322 билда.
    Плагины 1.4.5 r0.3 на 322 билде будут работать.
    Иду тестировать...
     
    MineMan910 и hilpavel нравится это.
  15. MySt1k

    MySt1k Старожил Пользователь

    Баллы:
    173
    Тест прошел успешно.
    Большинство плагинов работает.
    Не работает: WorldGuard
    Тест будет проверятся мной, список работающих и неработающих плагинов будет пополнятся.
     
    hilpavel и DPOH-VAR нравится это.
  16. MySt1k

    MySt1k Старожил Пользователь

    Баллы:
    173
    Тест №2 прошел успешно.
    Большинство плагинов работает.
    Из них: xAuth,WorldEdit,WorldBorder,AutoMessage,AntiShare,iConomy,iChat,HideStream,Essentials,MobArena,Scavenger,ChestShop,LWC,ruFix,Orebfuscator,PerformanceMonitor,Jobs...
    Не работает: WorldGuard,WGFixb.xd,LokiColor, NoCheatPlus...
    Список будет пополнятся.
     
    zuma2 и hilpavel нравится это.
  17. DPOH-VAR

    DPOH-VAR Старожил Пользователь

    Баллы:
    153
    Skype:
    dpohvar
    Эх... как же это бесит!
    Я нашел способ наеобмануть класслоадер с помощью прокси и рефлексий.
    Для мсье, знающих толк в извращениях.
    Инструкция:

    Создаем класс, который будет оперировать с объектами CraftBukkit:
    Код:
    /*
    Прошу прощения за имена классов и методов, но имхо они отражают всю суть последних обновлений 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:
    Код:
    interface VarItemStack {
        Material getType();
    }
    2) создаем объект таким образом:
    Код:
    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) используем наш объект как хотим. Например, так:
    Код:
    System.out.print(stack.getType());
    Другой вариант:
    Например у нас уже есть объект stack типа CraftItemStack, но хотим использовать его без импорта класса.
    Код:
    Object stack;
    Чтобы использовать его методы, делаем так:
    Код:
    VarItemStack myStack = VersionFucker.fuck(VarItemStack.class,stack);
    где параметры функции:
    1 - наш прокси-интерфейс​
    2 - наш объект​
    теперь можем в полной мере пользоваться его методами:
    Код:
    System.out.print(myStack .getType());
    Должно работать на всех версиях, с измененными названиями пакетов и оригинальными. Я проверял на v1_4_5 всего для нескольких типов объектов.
    Не тестировал для net.minecraft.server, но тоже должно работать.

    Это не является полноценным методом портирования плагина на все версии CraftBukkit (по большей части - костыль), но если использование CraftBukkit требуется отчасти и не во многих местах - он вполне подойдет.
     
    ITrAnEI, DoctorBooooom и fromgate нравится это.
  18. Автор темы
    fromgate

    fromgate Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    fromgate
    DPOH-VAR, застрелиться! Вчера тоже размышлял как бы обойти, но такое точно бы "не родил". Обязательно попробую. Если получится, то будет отлично. Будем дружно смеяться на буккитом.
     
    ITrAnEI и DPOH-VAR нравится это.
  19. Автор темы
    fromgate

    fromgate Старожил Пользователь

    Баллы:
    173
    Имя в Minecraft:
    fromgate
    А плагино 1.4.5-r0.2 на нем будут работать? Если нет, то это не фикс, а тоже самое.
     
    ITrAnEI нравится это.
  20. DPOH-VAR

    DPOH-VAR Старожил Пользователь

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

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

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