---
description: 定时器
---

# Timer

在实现后续的模块之前，我们首先需要实现一个⏲️ 定时器。⏲️ 定时器的作用在 [Scorpior 的文集](https://links.jianshu.com/go?to=https%3A%2F%2Fzhuanlan.zhihu.com%2Fp%2F104412058)当中已经详细阐述了。由于它的重要性，定时器是值得实现在内核当中。

但是，有一点需要考虑的是，⏲️ 定时器的触发是需要保证在 tick 一开始就执行的，例如，Creep transfer之后后一个 tick 的资源更新。

因此，在实现时保证 ⏲️ 定时器是发生在进程模块其他进程执行之前，即在内核构造时，注册定时器的触发为第一进程。

```typescript
/** 定时器模块 */
class Timer {
    /** 记录上一次调用 tick 的 Game.time 以保证每 tick 只能执行一次 tick */
    #lastTick: number = -1
    #tasks: {[tick: number]: {func: (...args) => any, params: any[]}[]} = {}
    /**
     * 添加定时任务
     */
    add(tick: number, func: (...args) => any, params: any[]) {
        assertWithMsg(tick > Game.time, `无法添加发生在当前 tick 或之前的定时任务`)

        if ( !(tick in this.#tasks) )
            this.#tasks[tick] = []
        
        this.#tasks[tick].push({ func, params })
    }
    /**
     * 在当前 tick 运行一次
     * 
     * 注意: 本函数每 tick 只能运行一次, 否则会报错.
     */
    tick() {
        // 检验为本 tick 第一次调用
        assertWithMsg(this.#lastTick === -1 || this.#lastTick !== Game.time, `定时器在 ${Game.time} 被重复调用 tick 函数`)

        if ( !(Game.time in this.#tasks) ) return
        for ( const { func, params } of this.#tasks[Game.time] ) {
            func.apply(undefined, params)
        }
        delete this.#tasks[Game.time]

        this.#lastTick = Game.time

        return OK
    }
}
```
