Bukkit事件监听器方法如何运行?

问题描述 投票:0回答:1

[用Java编写Minecraft插件时,您可以创建一个事件监听器方法,并随意命名,但是您必须传入事件监听器的类,例如:

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

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

java plugins minecraft bukkit
1个回答
1
投票

[注册实现Listener的实例时,Bukkit将使用反射检查带有@EventHandler批注和一个扩展了Event的参数的类中的每个方法。它会存储在注册表中,并在事件发生时被调用。

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

@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;
}
© www.soinside.com 2019 - 2024. All rights reserved.