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

Помогите Почему не работает евент?

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

  1. Автор темы
    IlyaHaker

    IlyaHaker Активный участник Пользователь

    Баллы:
    76
    Вот интерфейс с одним методом, чтобы его можно было использовать в лямбде
    Код:
    public interface EventProcessor<T extends Event> extends Listener {
        @EventHandler
        public void onEvent(T e);
    
        default void register(Main plugin) {
            plugin.getServer().getPluginManager().registerEvents(this, plugin);
        }
    }
    
    Вот само тело функции и регистрация листенера
    Код:
    EventProcessor<AsyncPlayerChatEvent> processor = (e) -> e.getPlayer().sendMessage("lambda is correct");
    processor.register(this);
    
    Почему это не работает?
     
  2. MurlikMurlik

    MurlikMurlik Активный участник Пользователь

    Баллы:
    96
    Может быть потому что тебе нужно юзать абстрактный класс а не интерфейс.
     
  3. CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Имя в Minecraft:
    Xezard
  4. Автор темы
    IlyaHaker

    IlyaHaker Активный участник Пользователь

    Баллы:
    76
    Ну как же? Я таким образом по факту создал объект, реализующий интерфейс EventProcessor<>
    Если делать это с помощью анонимного класса:
    Код:
    EventProcessor<AsyncPlayerChatEvent> processor = new EventProcessor<AsyncPlayerChatEvent>() {
       @Override
       @EventHandler
       public void onEvent(AsyncPlayerChatEvent e) {
          e.getPlayer().sendMessage("anon class is correct");
       }
    };
    
    То все будет работать
    Судя по всему проблема в том, что переопределенный метод не получает аннотации изначального метода
    Сделал я еще один метод интерфейса по умолчанию с этой аннотацией, а переопределенный вставил в тело этого метода
    Но теперь сервер думает, что тип параметра T это Event, а не тот, что я вписал
    Но как же так получается? В том же C++ шаблоны создают точно такой же класс, но вместо параметра будет выбран конкретный тип
     
  5. alexandrage

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

    Баллы:
    173
    Тут то и должно работать. А там не должно и не будет.
     
  6. alexandrage

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

    Баллы:
    173
    Вот тебе тестовый код, узнаешь сам почему не должно сработать.
    Код:
        private static List<Listener> Handlers = new ArrayList<Listener>();
    
        public static <T> T callEvent(T event) {
            Method[] methods;
            for (Object o : Handlers) {
                methods = o.getClass().getMethods();
                for (Method menhod : methods) {
                    if (menhod.getAnnotation(EventHandler.class) != null) {
                        try {
                            if (menhod.getParameterTypes()[0].isAssignableFrom(event.getClass())) {
                                menhod.invoke(o, event);
                            }
                        } catch (IllegalAccessException ex) {
                            ex.printStackTrace();
                        } catch (IllegalArgumentException ex) {
                            ex.printStackTrace();
                        } catch (InvocationTargetException ex) {
                            ex.printStackTrace();
                        }
                    }
                }
            }
            return (T) event;
        }
     
        public static void registerEvent(Listener o) {
            Handlers.add(o);
        }
    Код:
            registerEvent(new EventListener());
            PlayerInteractEvent event = new PlayerInteractEvent(null, null, null, null, null);
            callEvent(event);
     
  7. Автор темы
    IlyaHaker

    IlyaHaker Активный участник Пользователь

    Баллы:
    76
    Да, то, что я хотел сделать, сработало бы с шаблонами C++. Но тут сервер думает, что пришел метод типа Event и где-то в ходе работы он будет безопасно скастован. Я пытался в лямбде явно указать, что там AsyncPlayerChatEvent, но появляется ошибка. Может, можно как-то обойти эту ошибку?
     
  8. alexandrage

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

    Баллы:
    173
    Не юзать лямду. Так твой ивент никогда не вызовется. Первая причина, отсутствие анотации.
     
    Последнее редактирование: 22 авг 2019
  9. CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Имя в Minecraft:
    Xezard
    Если бы ты глянул репозиторий что я указал, ты бы понял, что возможно делать примерно вот так:
    Код:
    Events.subscribe(PlayerJoinEvent.class)
          .expireAfter(2, TimeUnit.MINUTES) // expire after 2 mins
          .expireAfter(1) // or after the event has been called 1 time
          .filter(e -> !e.getPlayer().isOp())
          .handler(e -> e.getPlayer().sendMessage("Wew! You were first to join the server since it restarted!"));
    
    Но делается это не в пару строк, что написал ты и совсем по-другому.
     
  10. Ission

    Ission Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    lokivava
    То, что в Java имеет похожий синтаксис на шаблоны, называется Generic и они мало имеют общего с настоящими шаблонами, они узкие и не дают почти никакой широты действий. Почитай про них и расстроишься.
     
  11. Автор темы
    IlyaHaker

    IlyaHaker Активный участник Пользователь

    Баллы:
    76
    Аннотация это не проблема, но видимо другая проблема, с дженериками, которая, по всей видимости, не решаема

    Я зашел в тот репозиторий, посмотрел, ничего не нашел и забил. Спасибо))

    Да, как оказалось и правда, только синтаксис похож. А жаль

    Всем спасибо!!
     
  12. Exception_Prototype

    Exception_Prototype Активный участник Пользователь

    Баллы:
    96
  13. CoolBoy

    CoolBoy Активный участник Пользователь

    Баллы:
    96
    Имя в Minecraft:
    Xezard
    Хорошо искал.
     
  14. Автор темы
    IlyaHaker

    IlyaHaker Активный участник Пользователь

    Баллы:
    76
    Поправочка, я не мог найти нужный класс до твоего примера
    А так, репозиторий большой, я минут 15 полистал, ничего не нашел и забил
     
  15. Luminate_

    Luminate_ Активный участник Пользователь

    Баллы:
    76
    Имя в Minecraft:
    Luminate_
    multi-catch юзать религия не позволяет?
     
  16. Dymeth

    Dymeth Активный участник Пользователь

    Баллы:
    98
    Имя в Minecraft:
    Dymeth
    Это auto-generated код на один раз для теста. Не придирайся ко всякой херне
     
  17. Luminate_

    Luminate_ Активный участник Пользователь

    Баллы:
    76
    Имя в Minecraft:
    Luminate_
    Да так, практикуюсь писать более компактный и читабельный код без костылей, вот и придераюсь куда попало
    :O
     

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