package ecs import ( "fmt" "reflect" "sync" "github.com/yohamta/donburi" "github.com/yohamta/donburi/features/events" ) // 事件订阅发布功能,底层使用donburi事件订阅发布 // 注意:事件订阅处理中应避免再次发布事件 // 事件相关定义 type ( // 事件类型定义 EventType[T any] struct { et *events.EventType[T] mu sync.Mutex // 锁 subMap map[string]events.Subscriber[T] } // 事件订阅者定义 Subscriber[T any] func(w World, event T) ) // 开启底层事件处理调试 func EventsDebugEnable() { events.Debug = true } // 创建事件类型的实例 func NewEventType[T any]() *EventType[T] { return &EventType[T]{ et: events.NewEventType[T](), mu: sync.Mutex{}, subMap: make(map[string]events.Subscriber[T], 0), } } // 迭代处理所有事件 func processAllEvents(w World) { events.ProcessAllEvents(w) } // 执行事件 func (me *EventType[T]) ProcessEvents(wd World) { me.mu.Lock() defer me.mu.Unlock() me.et.ProcessEvents(wd) } // 发布该类型的事件 func (me *EventType[T]) Publish(wd World, event *T) { me.mu.Lock() defer me.mu.Unlock() me.et.Publish(wd, *event) } // 订阅该类型的事件 func (me *EventType[T]) Subscribe(wd World, subscriber Subscriber[T]) { me.mu.Lock() defer me.mu.Unlock() sp := buildKey(wd, subscriber) if _, ok := me.subMap[sp]; ok { // 已经订阅过 return } sub := func(w donburi.World, event T) { subscriber(wd, event) } me.subMap[sp] = sub me.et.Subscribe(wd, sub) } // 取消订阅该类型的事件 func (me *EventType[T]) Unsubscribe(wd World, subscriber Subscriber[T]) { me.mu.Lock() defer me.mu.Unlock() sp := buildKey(wd, subscriber) if sub, ok := me.subMap[sp]; ok { // 存在, 取消订阅 me.et.Unsubscribe(wd, sub) } } // 生成订阅键 func buildKey[T any](wd World, subscriber Subscriber[T]) string { sp := fmt.Sprintf("%v_%v", wd.Id(), reflect.ValueOf(subscriber).Pointer()) return sp }