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

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

Если бы ты глянул репозиторий что я указал, ты бы понял, что возможно делать примерно вот так:
Код:
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!"));
Но делается это не в пару строк, что написал ты и совсем по-другому.
Я зашел в тот репозиторий, посмотрел, ничего не нашел и забил. Спасибо))

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

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


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


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

Всем спасибо!!
Хорошо искал.
 
Вот тебе тестовый код, узнаешь сам почему не должно сработать.
Код:
    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);
multi-catch юзать религия не позволяет?
 
Это auto-generated код на один раз для теста. Не придирайся ко всякой херне
Да так, практикуюсь писать более компактный и читабельный код без костылей, вот и придераюсь куда попало
:O
 
Назад
Верх