• 欢迎来到Minecraft插件百科!
  • 对百科编辑一脸懵逼?帮助:快速入门带您快速熟悉百科编辑!
  • 因近日遭受攻击,百科现已限制编辑,有意编辑请加入插件百科企鹅群:223812289

Event API Reference

来自Minecraft插件百科
Seesaw 233讨论 | 贡献2016年7月24日 (日) 11:49的版本 在监听器中反注册事件
跳转至: 导航搜索

点击此处浏览原文

Icon-info.png
本页面已存在其他语言的内容,请协助翻译为本地化的中文。
  • 点击此处开始翻译。
  • 如本模板出现在原文存档页面,请注意更新主页面后,仍需要去除此处该模板。
  • 如当前页面已经没有需要翻译的内容,请删去待翻译模板。
  • 有标题的大篇幅文章,如果短时间内无法全部翻译,请先把所有的标题翻译出来,以便之后的贡献者选择与翻译章节内容。

介绍

事件 是服务端用来告诉你在游戏中发生了什么的方式. Bukkit在许多类别中定义了许多事件; 例如 玩家的互动(玩家登录, 玩家点击了一个方块, 玩家死了,玩家重生...), 方块事件(方块被放置, 方块被破坏, 方块附近的实体被改变(它邻居变了233)...), 实体事件(一个怪物看上了你233, 一个苦力怕帮你收集土方块...), 世界事件 (一个世界被加载或卸载, 一个区块被加载或卸载), 以及许多. 由于MC官方的一些原因,他们的JavaDocs都挂了= =

基础

To keep this section simple, we're going to only work with PlayerLoginEvent. Lets start with setting up the method 为了保持简单易懂,这一节只讨论一种事件——PlayerLoginEnvent。让我们从创建一个监听/处理该事件的方法开始吧。

创建方法

In order for your plugin to handle an event call, you need to create a method for it: 为了让你的插件能够监听并处理该事件的回调,你需要为它创建一个方法。

@EventHandler
public void onLogin(PlayerLoginEvent event) {
    // 你自己的代码...
}

Before this method can be invoked by Bukkit when the "PlayerLoginEvent" is fired, we need to annotate it. We do this with EventHandlers. 你还需要向Bukkit声明一下,这样服务器才会在"PlayerLoginEvent"触发时调用该函数。我们需要用到EventHandlers来做到这一点。

@EventHandler

The "@EventHandler" class is an Annotation, which goes just above your method. It looks like this: “@EventHandler”类是一个Annotation,一般就放在你的方法上面。就像这样:

@EventHandler // EventPriority(事件优先级)默认为NORMAL

This marks your method as an EventHandler with the EventPriority as NORMAL. 这样一来,这一方法就标记为了一个EventPriority(事件优先级)为NORMAL的EventHandler(事件监听/处理器)。

The EventHandler can take an EventPriority to specify the priority of the method, like so: EventHandler可以通过EventPriority来自定义事件的优先级,例如:

@EventHandler(priority = EventPriority.HIGHEST) // 方法优先级设为最高
@EventHandler(priority = EventPriority.LOW) // 方法优先级设为低

Here's what it would look like in your class: 你的回调函数看起来应该和下面这个相类似:

@EventHandler
public void onLogin(PlayerLoginEvent event) {
    // 你自己的代码...
}

添加监听器

为了bukkit能够注册你的时间处理器,包含你事件处理方法的类必须implement了Listener接口(org.bukkit.event.Listener),例如:

public final class MyPlayerListener implements Listener {
    @EventHandler
    public void onLogin(PlayerLoginEvent event) {
        // Your code here...
    }
}

这个方法的名字(在上面的例子中的“onlogin”)并不重要;你可以给你的监听器任何只要你开心就好的名字。 你可能想知道:“bukkit怎么知道监听那个事件呢?”bukkit通过上面例子中你定义的“PlayerLoginEvent”这个方法的事件参数知道的。 Warning.png 你必须定义一个单个的事件否则Bukkit不会注册它的 你的插件的主类 (即extends JavaPlugin的那个类)也可以成为一个事件监听器, 并且这个可能在你的插件非常小的时候起作用,比如:

public class MyPlugin extends JavaPlugin implements Listener {
  @Override
  public void onEnable() {
    getServer().getPluginManager().registerEvents(this, this);
  }

  @EventHandler
  public void onLogin(PlayerLoginEvent event) {
    getLogger().log(Level.INFO, "Player " + event.getPlayer().getName() + " is logging in!");
  }
}

EventHandler参数

The @EventHandler annotation can take parameters to further define how the event handler behaves. At the moment you can specify:

Name Type Default Description Values
priority EventPriority EventPriority.NORMAL Sets the priority of your method
  • EventPriority.MONITOR
  • EventPriority.HIGHEST
  • EventPriority.HIGH
  • EventPriority.NORMAL
  • EventPriority.LOW
  • EventPriority.LOWEST
ignoreCancelled boolean false If set to true, your method will not get the event if the event has been cancelled
  • true
  • false


事件优先级

There are six priorities in Bukkit that are called in the following order

  • EventPriority.LOWEST
  • EventPriority.LOW
  • EventPriority.NORMAL
  • EventPriority.HIGH
  • EventPriority.HIGHEST
  • EventPriority.MONITOR

Every plugin gets a say in what happens, and every plugin must get a chance to know the outcome of an event. So, we pass events to plugins even after they've been cancelled. A plugin can actually uncancel an event after another plugin cancelled it. This is where priorities become really important.

Let's say a BLOCK_PLACE event is being handled. The lowest priority listener is called to get its say in whether it should be cancelled or not. Then the low priority listener is called to see if it wants to override the lowest, etc. Eventually it hits monitor, and at this point nothing should change the outcome of the event. Monitor should be used to see the outcome of an event, without changing any aspect of it. If we have three plugins enabled; one is a basic area protection plugin, one is a fancy plugin using signs, and another is a logging plugin. The protection plugin listens on Priority.LOWEST. It says they can't place blocks in this area, and cancels the event. The fancy sign plugin listens on Priority.NORMAL. It says they can place signs here, and uncancels the event. The log plugin listens on Priority.MONITOR. It sees that the event was actually allowed, and logs it.

If you want to change the outcome of an event, choose very carefully from LOWEST to HIGHEST. Suggested generalized protection plugins on lowest, more specific plugins on normal, and override plugins on high. If you want to act when an event happens, but not change the outcome, use MONITOR. It's really really important that you use MONITOR, or an event might get cancelled after you've acted on it, and it's even more important that you don't change the outcome of the event on MONITOR or it'll break other plugins.

中文简单解释

优先级越高的方法越早调用

优先级再高(除了MONITOR) setCanceled() 方法也不能阻止其它插件监听到它

在MONITOR上搞 setCanceled(false) 其它插件会给你玩死~

注册事件(监听器)

要注册你的方法,包含EventHandler的类必须是implent了Listenr类的

import org.bukkit.event.Listener;

public final class LoginListener implements Listener {
}

你只需要提供一个插件和一个监听器来在PluginManager里注册它们

getServer().getPluginManager().registerEvents(Listener, Plugin);

监听器示例

这个监听器包含两个EventHandlers,一个监听级别是HIGH并且另一个是NORMAL。

import org.bukkit.event.Listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerLoginEvent;

public final class LoginListener implements Listener {
    @EventHandler
    public void normalLogin(PlayerLoginEvent event) {
        // Some code here
    }

    @EventHandler(priority = EventPriority.HIGH)
    public void highLogin(PlayerLoginEvent event) {
        // Some code here
    }
}

在插件中注册事件监听器

The registerEvents method requires a listener and a plugin. Luckily, we already have our LoginListener. Now for the LoginPlugin!

import org.bukkit.plugin.java.JavaPlugin;

public final class LoginPlugin extends JavaPlugin {
    public void onEnable() {
        getServer().getPluginManager().registerEvents(new LoginListener(), this);
    }
}


在实现监听器接口的插件中注册事件监听器

[1] You could even have the events in the main class, for example:

import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.event.Listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerLoginEvent;

public final class LoginPlugin extends JavaPlugin implements Listener {
    public void onEnable() {
        getServer().getPluginManager().registerEvents(this, this);
    }

    @EventHandler
    public void normalLogin(PlayerLoginEvent event) {
        // Some code here
    }
}

在监听器中注册事件监听器

There are many ways to register your events. Here's an example where you register them in your listener class.

import org.bukkit.event.Listener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerLoginEvent;

public final class LoginListener implements Listener {
    public LoginListener(LoginPlugin plugin) {
        plugin.getServer().getPluginManager().registerEvents(this, plugin);
    }

    @EventHandler
    public void normalLogin(PlayerLoginEvent event) {
        // Some code here
    }

    @EventHandler(priority = EventPriority.HIGH)
    public void highLogin(PlayerLoginEvent event) {
        // Some code here
    }
}

The LoginPlugin would look like this:

import org.bukkit.plugin.java.JavaPlugin;

public final class LoginPlugin extends JavaPlugin {
    public void onEnable() {
        new LoginListener(this);
    }
}

在监听器中注销事件监听器

You can un-register individual events, entire listener classes or all events registered by your plugin or even by other plugins!

注销特定的事件监听器

Each event class has the getHandlerList() static method, call that and then you can use .unregister() method. Example:

PlayerInteractEvent.getHandlerList().unregister(plugin);
// this will unregister all PlayerInteractEvent instances from the plugin
// you can also specify a listener class instead of plugin.

Now you know why you'll need the getHandlerList() in your custom events.

注销所有事件监听器

Using the HandlerList class and its unregisterAll() static method you can easily unregister events from listener classes or plugins. Example:

HandlerList.unregisterAll(plugin);
// this will unregister all events from the specified plugin
// you can also specify a listener class instead of plugin.

创建自定义事件

Creating custom events is very simple, you can use the same system that Bukkit uses without ruining performance.

There are two (2) things to keep in mind when you create a Custom Event. They are "extend Event" and "static handlers." With static handlers, you must input the following code into your custom event:

private static final HandlerList handlers = new HandlerList();

public HandlerList getHandlers() {
    return handlers;
}

public static HandlerList getHandlerList() {
    return handlers;
}

This block of code makes the EventHandlers contained inside your own event, keeping any unrelated events completely separated.

自定义事件示例

The following example shows how easy it is to create your own "CustomEvent."

import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;

public final class CustomEvent extends Event {
    private static final HandlerList handlers = new HandlerList();
    private String message;

    public CustomEvent(String example) {
        message = example;
    }

    public String getMessage() {
        return message;
    }

    public HandlerList getHandlers() {
        return handlers;
    }

    public static HandlerList getHandlerList() {
        return handlers;
    }
}

调用你的自定义事件

You are in control of creating and calling your events, where you call it is completely up to you. Here's an example

// Create the event here
CustomEvent event = new CustomEvent("Sample Message");
// Call the event
Bukkit.getServer().getPluginManager().callEvent(event);
// Now you do the event
Bukkit.getServer().broadcastMessage(event.getMessage());

Remember: You are in control of your events. If you don't call it, and act upon it, it doesn't happen!

监听一个自定义事件

How do you listen to a custom event you say? Simple, the same way as listening to a normal event!

import org.bukkit.event.Listener;
import org.bukkit.event.EventHandler;

public final class CustomListener implements Listener {
    @EventHandler
    public void normalLogin(CustomEvent event) {
        // Some code here
    }
}

使得你的自定义事件具有可撤销性

If you ever want to make your event cancellable, remember one thing: "implements Cancellable." Just like you would import Listener. It's really that simple, let me show you an example!

import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Cancellable;

public final class CustomEvent extends Event implements Cancellable {
    private static final HandlerList handlers = new HandlerList();
    private String message;
    private boolean cancelled;

    public CustomEvent(String example) {
        message = example;
    }

    public String getMessage() {
        return message;
    }

    public boolean isCancelled() {
        return cancelled;
    }

    public void setCancelled(boolean cancel) {
        cancelled = cancel;
    }

    public HandlerList getHandlers() {
        return handlers;
    }

    public static HandlerList getHandlerList() {
        return handlers;
    }
}

Afterwards, you would check if a plugin had cancelled the event in your code, before processing normally

// Create the event here
CustomEvent event = new CustomEvent("Sample Message");
// Call the event
Bukkit.getServer().getPluginManager().callEvent(event);
// Check if the event is not cancelled
if (!event.isCancelled()) {
    // Now you do the event
    Bukkit.getServer().broadcastMessage(event.getMessage());
}

视频教程

If you would prefer to watch a video tutorial version of this, please click here.

  1. 准确来说是在实现了监听器接口的继承了JavaPlugin的类中注册事件(笑