colinhdev/libasyncevent

为 PocketMine-MP 插件创建异步事件执行的简单实现。

v3.0.0 2024-08-23 01:23 UTC

This package is auto-updated.

Last update: 2024-09-23 01:44:34 UTC


README

libAsyncEvent 为您提供了为 PocketMine-MP 插件创建异步事件执行的多重实现。

为什么我应该使用这个库?

当我正在将 libasynqlawait-generator 实现到我的插件 CPlot 中时,我萌生了创建这个库的想法。我意识到在这种情况下处理 PocketMine-MP 的事件是多么烦恼,因为在这种情况下无法使用异步运行的查询来检查玩家是否有权在特定区域建造。

因此,当我决定在插件中实现自定义事件时,我希望使其尽可能开发者友好。所以当有人决定与事件一起工作时,他们不必直接决定如何反应(例如取消事件),并允许运行异步查询以验证他们的决定。

如何在插件中使用这个库?

我的事件类应该如何看起来?

通常,你的事件类看起来像这样:它扩展了 PocketMine-MP 的 Event 类或其子类,并可能还实现了像 Cancellable 这样的接口。

use pocketmine\event\Event;
use pocketmine\event\Cancellable;

class MyEvent extends Event implements Cancellable {}

首先,在你的事件类中实现这个库提供的 AsyncEvent 接口。其次,在你的事件类中使用 EventHandlerExecutionTrait 之一。

use ColinHDev\libAsyncEvent\AsyncEvent;
use ColinHDev\libAsyncEvent\SomeEventHandlerExecutionTrait;
use pocketmine\event\Event;
use pocketmine\event\Cancellable;

class MyEvent extends Event implements AsyncEvent, Cancellable {
    use SomeEventHandlerExecutionTrait;
}

有多种 EventHandlerExecutionTrait 可以使用,每个都有不同的行为

  • ConsecutiveEventHandlerExecutionTrait:这个特性将依次执行所有事件监听器。如果一个 block() 执行,则下一个监听器仅在当前监听器调用 release() 后才会执行。
  • PriorityEventHandlerExecutionTrait:这个特性将同时执行相同优先级的所有事件监听器。如果一个或多个监听器 block() 执行,则高优先级的监听器仅在所有 block() 的监听器调用 release() 后才会执行。

我如何调用我的事件?

你可以简单地通过创建一个新的事件实例并使用其 call() 方法来调用你的事件。

$event = new MyEvent();
$event->call();

但要获取事件的结果,你需要提供一个回调函数,该函数将在所有监听器完成时运行。

$event = new MyEvent();
$event->setCallback(
    function (MyEvent $event) : void {
        if ($event->isCancelled()) {
            // do something
        } else {
            // do something else
        }
    }
);
$event->call();

如何改进我的事件类?

除非你和使用异步事件注册监听器的人都在使用 composer,否则他们无法在 IDE 中正确地看到 libAsyncEvent 声明的方法,如 block()release()

尽管理想情况下应使用 composer 开发插件并声明其依赖项,但我们不能强迫任何人这样做。因此,为了使他们更容易做到这一点,你可以在事件类中添加以下 PHPDoc 注释:

/**
 * @link https://github.com/ColinHDev/libAsyncEvent/
 * @method void block()
 * @method void release()
 */
class MyEvent extends Event implements AsyncEvent, Cancellable {}

这样,IDE 就会知道这些方法存在,而不会显示任何错误。

如何处理使用此库创建的事件?

要为异步事件注册事件监听器,你可以像通常为其他事件监听器做的那样做。

Server::getInstance()->getPluginManager()->registerEvents(new MyListener(), $this);

在这个类中,你也可以创建一个方法,该方法接受你想要监听的事件作为参数

    public function onMyEvent(MyEvent $event) : void {
        // do something
    }

所以基本上,普通事件监听器和我们的异步事件监听器之间没有区别。但是,如果你想阻止事件实例继续执行,你需要调用 block() 方法。这样,事件将不会执行完毕,直到你调用 release() 方法。

    public function onMyEvent(MyEvent $event) : void {
        // some synchronous logic here
        $event->block();
        // some asynchronous logic here
        $event->release();
    }

如果你不小心忘记调用 release() 方法,一旦事件实例被垃圾回收器销毁,将会抛出异常。