refactor: EventEmitter3
This commit is contained in:
@@ -3,6 +3,7 @@ import type { Message } from 'neuri/openai'
|
||||
import type { z } from 'zod'
|
||||
import type { MineflayerPlugin } from './plugin'
|
||||
import { useLogg } from '@guiiai/logg'
|
||||
import EventEmitter from 'eventemitter3'
|
||||
import mineflayer from 'mineflayer'
|
||||
import { type CommandContext, parseCommand } from './command'
|
||||
import { formBotChat } from './message'
|
||||
@@ -26,16 +27,6 @@ export type EventsHandler<K extends Events> = EventHandlers[K]
|
||||
|
||||
export type Handler = (ctx: Context) => void | Promise<void>
|
||||
|
||||
function createEventHandlers(): Record<Events, Array<EventsHandler<Events>>> {
|
||||
return {
|
||||
'command': [],
|
||||
'time:sunrise': [],
|
||||
'time:noon': [],
|
||||
'time:sunset': [],
|
||||
'time:midnight': [],
|
||||
}
|
||||
}
|
||||
|
||||
export class Health {
|
||||
public value: number
|
||||
public lastDamageTime?: number
|
||||
@@ -133,7 +124,7 @@ export interface MineflayerOptions {
|
||||
plugins?: Array<MineflayerPlugin>
|
||||
}
|
||||
|
||||
export class Mineflayer {
|
||||
export class Mineflayer extends EventEmitter<EventHandlers> {
|
||||
public bot: Bot
|
||||
public username: string
|
||||
public health: Health = new Health()
|
||||
@@ -149,10 +140,10 @@ export class Mineflayer {
|
||||
private options: MineflayerOptions
|
||||
private logger: ReturnType<typeof useLogg>
|
||||
private commands: Map<string, EventsHandler<'command'>> = new Map()
|
||||
private eventHandlers = createEventHandlers()
|
||||
private ticker: Ticker = new Ticker()
|
||||
|
||||
constructor(options: MineflayerOptions) {
|
||||
super()
|
||||
this.options = options
|
||||
this.bot = mineflayer.createBot(options.botConfig)
|
||||
this.username = options.botConfig.username
|
||||
@@ -277,10 +268,7 @@ export class Mineflayer {
|
||||
}
|
||||
|
||||
public emit<E extends Events>(event: E, ...args: Parameters<EventsHandler<E>>) {
|
||||
const handlers = this.eventHandlers[event]
|
||||
for (const handler of handlers) {
|
||||
handler(args[0])
|
||||
}
|
||||
return super.emit(event, ...args)
|
||||
}
|
||||
|
||||
public async stop() {
|
||||
@@ -292,6 +280,7 @@ export class Mineflayer {
|
||||
this.components.cleanup()
|
||||
this.bot.removeListener('chat', this.handleCommand())
|
||||
this.bot.end()
|
||||
this.removeAllListeners()
|
||||
}
|
||||
|
||||
private handleCommand() {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import EventEmitter from 'eventemitter3'
|
||||
|
||||
export interface TickContext {
|
||||
delta: number
|
||||
nextTick: () => Promise<void>
|
||||
@@ -11,29 +13,23 @@ export type TickEvents = keyof TickEventHandlers
|
||||
export type TickEventsHandler<K extends TickEvents> = 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 {
|
||||
private tickingCbs: Record<TickEvents, Array<TickEventHandlers[TickEvents]>> = {
|
||||
tick: [],
|
||||
}
|
||||
|
||||
export class Ticker extends EventEmitter<TickEventHandlers> {
|
||||
constructor(options?: { interval?: number }) {
|
||||
super()
|
||||
const { interval = 300 } = options ?? { interval: 300 }
|
||||
|
||||
let last = Date.now()
|
||||
const tickingCbs: Record<TickEvents, Array<TickEventHandlers[TickEvents]>> = {
|
||||
tick: [],
|
||||
}
|
||||
|
||||
setTimeout(async () => {
|
||||
while (true) {
|
||||
const start = Date.now()
|
||||
const nextTickPromise = new Promise<void>((resolve) => {
|
||||
// Schedule nextTick resolution for after all callbacks complete
|
||||
// Schedule nextTick resolution for after all callbacks complete
|
||||
setImmediate(resolve)
|
||||
})
|
||||
|
||||
// Run all callbacks without awaiting them
|
||||
const callbackPromises = tickingCbs.tick.map(cb => cb({
|
||||
const callbackPromises = this.listeners('tick').map(cb => cb({
|
||||
delta: start - last,
|
||||
nextTick: () => nextTickPromise,
|
||||
}))
|
||||
@@ -47,9 +43,8 @@ export class Ticker {
|
||||
])
|
||||
|
||||
const remaining = interval - (Date.now() - start)
|
||||
if (remaining > 0) {
|
||||
if (remaining > 0)
|
||||
await new Promise(resolve => setTimeout(resolve, remaining))
|
||||
}
|
||||
|
||||
last = start
|
||||
}
|
||||
@@ -57,6 +52,6 @@ export class Ticker {
|
||||
}
|
||||
|
||||
on<K extends TickEvents>(event: K, cb: TickEventsHandler<K>) {
|
||||
this.tickingCbs[event].push(cb)
|
||||
return super.on(event, cb)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user