diff --git a/services/minecraft/src/libs/mineflayer/core.ts b/services/minecraft/src/libs/mineflayer/core.ts index c17155770..dffdf0384 100644 --- a/services/minecraft/src/libs/mineflayer/core.ts +++ b/services/minecraft/src/libs/mineflayer/core.ts @@ -168,6 +168,8 @@ export class Mineflayer extends EventEmitter { this.respawnTimer = null } + this.ticker.stop() + await this.pluginRuntime.beforeCleanup() this.components.cleanup() this.detachCommandChatListener() diff --git a/services/minecraft/src/libs/mineflayer/ticker.ts b/services/minecraft/src/libs/mineflayer/ticker.ts index 87f3f884b..96502c8e9 100644 --- a/services/minecraft/src/libs/mineflayer/ticker.ts +++ b/services/minecraft/src/libs/mineflayer/ticker.ts @@ -14,14 +14,19 @@ export type TickEventsHandler = TickEventHandlers[K] // This update loop ensures that each update() is called one at a time, even if it takes longer than the interval export class Ticker extends EventEmitter { + private stopping = false + private initialTimer: ReturnType | null = null + constructor(options?: { interval?: number }) { super() const { interval = 300 } = options ?? { interval: 300 } let last = Date.now() - setTimeout(async () => { - while (true) { + this.initialTimer = setTimeout(async () => { + this.initialTimer = null + + while (!this.stopping) { const start = Date.now() const nextTickPromise = new Promise((resolve) => { // Schedule nextTick resolution for after all callbacks complete @@ -43,7 +48,7 @@ export class Ticker extends EventEmitter { ]) const remaining = interval - (Date.now() - start) - if (remaining > 0) + if (remaining > 0 && !this.stopping) await new Promise(resolve => setTimeout(resolve, remaining)) last = start @@ -54,4 +59,15 @@ export class Ticker extends EventEmitter { on(event: K, cb: TickEventsHandler) { return super.on(event, cb) } + + stop() { + this.stopping = true + + if (this.initialTimer) { + clearTimeout(this.initialTimer) + this.initialTimer = null + } + + this.removeAllListeners() + } }