Skip to content

定义任务

通过PySpigot,脚本可以与Bukkit的任务调度器交互,并安排/运行同步和异步任务。这些任务允许您在以后的时间运行代码,以间隔运行,重复运行,并在非主服务器线程上运行。任务管理器还内置了对具有同步回调的异步任务的支持。

要了解如何将任务管理器导入到您的脚本中,请访问General Information页面。

详情

这不是一个关于安排任务的详尽指南。要获得有关任务和调度器编程的更完整指南,请参阅Bukkit关于使用调度器的教程这里。请注意,许多信息都涉及在Java中编写插件,但一般概念仍然有助于理解。

任务管理器使用

任务管理器中有几个函数可供您在脚本中使用:

  • runTask(function, functionArgs): 尽快运行一个同步任务。需要指定任务运行时要调用的函数,并且可以传递任意数量的参数给函数。
  • runTaskAsync(function, functionArgs): 运行一个异步任务(在主服务器线程之外的线程上执行)。需要指定任务运行时要调用的函数,并且可以传递任意数量的参数给函数。
  • runTaskLater(function, delay, functionArgs): 在未来的某个时间点运行一个同步任务,延迟一定时间后执行。需要指定任务运行时要调用的函数、等待的延迟时间(以ticks为单位),以及传递给函数的任意数量参数。
  • runTaskLaterAsync(function, delay, functionArgs): 在未来的某个时间点运行一个异步任务,延迟一定时间后执行。需要指定任务运行时要调用的函数、等待的延迟时间(以ticks为单位),以及传递给函数的任意数量参数。
  • scheduleRepeatingTask(function, delay, interval, functionArgs): 运行一个重复执行的同步任务,每隔指定的间隔重复执行。需要指定每次任务运行时要调用的函数、在运行任务之前等待的延迟时间(以ticks为单位)以及任务应该运行的间隔(以ticks为单位),以及传递给函数的任意数量参数。
  • scheduleAsyncRepeatingTask(function, delay, interval, functionArgs): 运行一个重复执行的异步任务,每隔指定的间隔重复执行。需要指定每次任务运行时要调用的函数、在运行任务之前等待的延迟时间(以ticks为单位)以及任务应该运行的间隔(以ticks为单位),以及传递给函数的任意数量参数。
  • runSyncCallbackTask(function, callback, functionArgs): 调度一个带有同步回调的异步任务。需要指定异步部分要调用的函数,以及同步部分要调用的另一个函数。同时还可以传递任意数量的参数给函数(异步部分)。
  • runSyncCallbackTaskLater(function, callback, delay, functionArgs): 调度一个带有同步回调的异步任务,延迟一定时间后执行。需要指定异步部分要调用的函数,同步部分要调用的另一个函数,以及延迟等待的时间(以ticks为单位)之后运行任务。同时还可以传递任意数量的参数给函数(异步部分)。
  • stopTask(id): 停止/取消一个任务。需要传递要停止的任务的id。任何时候都会返回一个任务ID(int),该ID可用于以后取消任务(如果需要)。

在上述函数中,functionArgs是可选参数。如果要调用的函数不接受任何参数,则无需指定任何参数。

游戏内20个刻钟对应现实世界的1秒(在没有TPS延迟的服务器上)。因此,1个刻钟等于1/20秒。

基本代码示例

让我们看一下以下定义和启动同步重复任务的代码:

1
2
3
4
5
6
7
8
import pyspigot as ps # (1)!

a_string = 'Test'

def run_task(arg): # (2)!
    #Do something...

task_id = ps.scheduler.scheduleRepeatingTask(run_task, 0, 100, a_string) # (3)!
  1. 在这里,我们导入PySpigot作为ps以利用任务管理器(scheduler)。

  2. 在这里,我们定义一个名为run_task的函数,该函数接受一个参数。

  3. 在这里,我们通过任务管理器向注册我们的任务作为同步重复任务,传递run_task函数、我们期望的延迟(0刻钟)、期望的时间间隔(100刻钟)以及我们希望每次运行任务时传递给任务函数的变量(我们在第3行早些时候定义的a_string变量)。然后将返回的值赋给task_id,这是一个int,是注册的任务的ID。此ID可用于以后取消/停止任务。

与监听器一样,所有任务都必须在PySpigot的任务管理器中注册和运行。根据我们希望任务是同步的、异步的和/或重复的方式,有许多不同的启动任务的方法,但在这里我们希望我们的任务是同步的和重复的,所以我们使用scheduleRepeatingTask(function, delay, interval, functionArgs),在这种情况下需要四个参数:

  • 第一个参数是接受一个函数,该函数在任务运行时应被调用(无论是一次性还是按固定间隔重复调用)。
  • 第二个参数是调度程序在注册任务时应等待的延迟时间(以滴答数计)。
  • 第三个参数是任务运行的间隔时间(以滴答数计)。
  • 最后的参数(在本例中仅为第四个)用于指定应传递给函数的参数。

将多个参数传递给任务函数

如果我们想要修改上面示例中的 run_task 函数,使其接受两个参数而不是一个,我们可以像下面修改代码:

1
2
3
4
5
6
7
8
9
import pyspigot as ps

a_string = 'Test'
another_string = 'Test 2'

def run_task(arg, arg2):
    #Do something...

task_id = ps.scheduler.scheduleRepeatingTask(run_task, 0, 100, a_string, another_string)

这个示例与第一个示例非常相似,不同之处在于我们定义了另一个字符串(another_string),并在注册任务时(第8行)将其(以及a_string)传递给任务管理器。然后这两个字符串按顺序传递给 run_task 函数,当该函数被任务调用时。

正如您所见,要传递的所有参数均添加到注册任务的函数末尾,按照应该传递它们的顺序。

任务管理器还包括回调任务,这是一种特殊任务,它会异步运行,然后在异步任务完成后运行另一个同步任务。这种任务类型在希望以异步方式处理工作,然后在同步上下文中处理该工作的情况下非常有用。例如,考虑这样一种情况:服务器有一个存储玩家数据的SQL数据库。当玩家加入时,应该异步地从数据库中获取数据以避免服务器延迟,但不能异步地应用于玩家,因为所有与Bukkit和服务器的交互都应该是同步的。因此,在这种情况下,同步回调非常有用,可以将从数据库获取的数据带回主服务器线程进行进一步处理,并应用到玩家身上。

回调任务示例

以下是如何使用回调任务的简单示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import pyspigot as ps

def async_task():
    print('异步!')
    data = '一些数据'
    return data

def sync_task(data):
    print('同步!')
    print(data)

ps.scheduler.runSyncCallbackTask(async_task, sync_task)

观察到以下控制台输出:

1
2
3
[STDOUT] 异步!
[STDOUT] 同步!
[STDOUT] 一些数据

关于这个示例需要注意的几点:

  • 首先,为回调任务的异步和同步部分定义了不同的函数。
  • 其次,异步任务首先执行,直到异步任务完成后,同步任务才会开始执行。
  • 第三,从任务的异步部分返回的任何数据(例如上面示例的第6行中的返回语句)都作为参数传递给任务的同步部分(sync_task在上面接受参数data)。这允许对在任务的异步部分获取的任何数据进行同步处理。

摘要

  • 类似侦听器,任务在您的脚本中被定义为函数。任务可以携带任意数量的参数,包括零个。
  • 任务可以将参数传递给它们调用的函数。在向任务管理器注册任务时指定这些参数。
  • 所有任务都必须在PySpigot的任务管理器中注册。例如,要安排和运行一个同步重复任务,使用scheduler.scheduleRepeatingTask(function, delay, interval, functionArgs)