当前位置: 首页 > 知识库问答 >
问题:

Bukkit事件侦听器方法是如何运行的?

巢德华
2023-03-14

在用java编写Minecraft插件时,您可以创建一个事件监听器方法,并将其命名为任意名称,但您必须传入事件监听者的类,例如:

@EventListener
public void onPlayerJoin(PlayerJoinEvent event) {
     // code here
}

我只是想知道,如果Bukkit API中的任何类都不知道该方法的名称,那么该方法是如何在“幕后”执行的?我希望我能很好地解释自己。谢谢

共有1个答案

危宜
2023-03-14

当注册一个实现<code>Listener</code>的实例时,Bukkit将使用反射来检查该类中的每个方法,该类带有<code>@EventHandler</ccode>注释和一个扩展<code>Event</code>的参数。它将存储在注册表中,并在事件发生时调用。

编辑:您可能对下面的源代码感兴趣。源

@Override
@NotNull
public Map<Class<? extends Event>, Set<RegisteredListener>> createRegisteredListeners(@NotNull Listener listener, @NotNull final Plugin plugin) {
    Validate.notNull(plugin, "Plugin can not be null");
    Validate.notNull(listener, "Listener can not be null");

    boolean useTimings = server.getPluginManager().useTimings();
    Map<Class<? extends Event>, Set<RegisteredListener>> ret = new HashMap<Class<? extends Event>, Set<RegisteredListener>>();
    Set<Method> methods;
    try {
        Method[] publicMethods = listener.getClass().getMethods();
        Method[] privateMethods = listener.getClass().getDeclaredMethods();
        methods = new HashSet<Method>(publicMethods.length + privateMethods.length, 1.0f);
        for (Method method : publicMethods) {
            methods.add(method);
        }
        for (Method method : privateMethods) {
            methods.add(method);
        }
    } catch (NoClassDefFoundError e) {
        plugin.getLogger().severe("Plugin " + plugin.getDescription().getFullName() + " has failed to register events for " + listener.getClass() + " because " + e.getMessage() + " does not exist.");
        return ret;
    }

    for (final Method method : methods) {
        final EventHandler eh = method.getAnnotation(EventHandler.class);
        if (eh == null) continue;
        // Do not register bridge or synthetic methods to avoid event duplication
        // Fixes SPIGOT-893
        if (method.isBridge() || method.isSynthetic()) {
            continue;
        }
        final Class<?> checkClass;
        if (method.getParameterTypes().length != 1 || !Event.class.isAssignableFrom(checkClass = method.getParameterTypes()[0])) {
            plugin.getLogger().severe(plugin.getDescription().getFullName() + " attempted to register an invalid EventHandler method signature \"" + method.toGenericString() + "\" in " + listener.getClass());
            continue;
        }
        final Class<? extends Event> eventClass = checkClass.asSubclass(Event.class);
        method.setAccessible(true);
        Set<RegisteredListener> eventSet = ret.get(eventClass);
        if (eventSet == null) {
            eventSet = new HashSet<RegisteredListener>();
            ret.put(eventClass, eventSet);
        }

        for (Class<?> clazz = eventClass; Event.class.isAssignableFrom(clazz); clazz = clazz.getSuperclass()) {
            // This loop checks for extending deprecated events
            if (clazz.getAnnotation(Deprecated.class) != null) {
                Warning warning = clazz.getAnnotation(Warning.class);
                WarningState warningState = server.getWarningState();
                if (!warningState.printFor(warning)) {
                    break;
                }
                plugin.getLogger().log(
                        Level.WARNING,
                        String.format(
                                "\"%s\" has registered a listener for %s on method \"%s\", but the event is Deprecated. \"%s\"; please notify the authors %s.",
                                plugin.getDescription().getFullName(),
                                clazz.getName(),
                                method.toGenericString(),
                                (warning != null && warning.reason().length() != 0) ? warning.reason() : "Server performance will be affected",
                                Arrays.toString(plugin.getDescription().getAuthors().toArray())),
                        warningState == WarningState.ON ? new AuthorNagException(null) : null);
                break;
            }
        }

        EventExecutor executor = new EventExecutor() {
            @Override
            public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
                try {
                    if (!eventClass.isAssignableFrom(event.getClass())) {
                        return;
                    }
                    method.invoke(listener, event);
                } catch (InvocationTargetException ex) {
                    throw new EventException(ex.getCause());
                } catch (Throwable t) {
                    throw new EventException(t);
                }
            }
        };
        if (useTimings) {
            eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled()));
        } else {
            eventSet.add(new RegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled()));
        }
    }
    return ret;
}
 类似资料:
  • 嗨,我有这个问题与我的代码每次我使一个对象在监听器类的监听器将不工作例如。 我在我的主类(CSmain.java)中有这个公共变量: 我在类中还有一个名为getSpawn()的方法,它返回spawn: 我已经在我的onEnable()中初始化了这个变量,但是当我试图从我的另一个类中获取它时,这个类(JoinListener.java)将无法工作。 我测试了它没有创建对象(CSmain main C

  • 我正试着做一个插件,你输入命令/设置,它就切换布尔设置。如果set是真的,我希望当玩家加入时,它对他们说“嗨”,但如果set是假的,它什么也不做。(顺便说一句,我是唯一可以使用这个命令的人)。我试着创建两个类,一个是主类,另一个是侦听器类,但是我不能从侦听器类访问布尔值,所以我试着把它们都放在一个类中。当使用我提供的代码时,除了PlayerJoinEvent之外,一切都正常。我要么需要解决如何从另

  • 我正在编写一个手势/动作库,它还管理事件侦听器和触发。我已经实现了我的库,通过一个API支持手势对象设置被动侦听器,该API如下:。My lib支持多种手势,设置多个听众,包括被动和非被动。lib将确保最多只有一个真正的侦听器连接到DOM。因此,我们最多可以有2个touchstart监听器,其中一个是被动监听器,另一个不是。 我的问题和问题是,我无法检测接收到的事件是否附加了选项。我认为我可以在本

  • 我可以在下面的代码中为添加事件侦听器,但不能添加到。 是不是因为twitter做了一些事情不让我这么做?有办法绕过它吗?

  • 本文向大家介绍用js写一个事件侦听器的方法相关面试题,主要包含被问及用js写一个事件侦听器的方法时的应答技巧和注意事项,需要的朋友参考一下

  • 在致力于提高渐进式web应用程序的性能时,我遇到了一个新功能,我发现很难理解这个概念。 什么是被动事件侦听器,在我们的项目中需要它吗?