package ecs import ( "fmt" "reflect" "sync" "github.com/yohamta/donburi" "github.com/yohamta/donburi/features/events" ) // 注意事件相关操作的最终执行者均为world协程 // 事件相关定义 type ( // 事件类型定义 EventType[T any] struct { et *events.EventType[T] subscriberMap map[string]events.Subscriber[T] subscriberMapLock sync.Mutex // } // 事件订阅者定义 Subscriber[T any] func(w World, event T) // 事件管理回调定义 ManageEventFunc func() ) // 开启底层事件处理调试 func EventsDebugEnable() { events.Debug = true } // 创建事件类型的实例 func NewEventType[T any]() *EventType[T] { return &EventType[T]{ et: events.NewEventType[T](), subscriberMap: make(map[string]events.Subscriber[T]), subscriberMapLock: sync.Mutex{}, } } // 迭代处理所有事件 // 在world协程中执行 func processAllEvents(w World) { events.ProcessAllEvents(w.(*world).world) } // 订阅该类型的事件 func (me *EventType[T]) Subscribe(wd World, subscriber Subscriber[T]) { if wd.GoroutineId() == currentGoId() { me.subscribe(wd, subscriber) } else { wd.(*world).chanManageEvent <- func() { me.subscribe(wd, subscriber) } } } // 取消订阅该类型的事件 func (me *EventType[T]) Unsubscribe(wd World, subscriber Subscriber[T]) { if wd.GoroutineId() == currentGoId() { me.unsubscribe(wd, subscriber) } else { wd.(*world).chanManageEvent <- func() { me.unsubscribe(wd, subscriber) } } } // 发布该类型的事件 func (me *EventType[T]) Publish(wd World, event *T) { if wd.GoroutineId() == currentGoId() { me.publish(wd, event) } else { wd.(*world).chanManageEvent <- func() { me.publish(wd, event) } } } /////////////////////////////////////////////////////////////////////////////////// // 订阅该类型的事件 func (me *EventType[T]) subscribe(wd World, subscriber Subscriber[T]) { me.subscriberMapLock.Lock() defer me.subscriberMapLock.Unlock() // subscriberKey := subscriberKey[T](wd, subscriber) if _, exist := me.subscriberMap[subscriberKey]; !exist { me.subscriberMap[subscriberKey] = func(w donburi.World, event T) { subscriber(wd, event) } me.et.Subscribe(wd.(*world).world, me.subscriberMap[subscriberKey]) } else { panic("重复注册事件订阅者") } } // 取消订阅该类型的事件 func (me *EventType[T]) unsubscribe(wd World, subscriber Subscriber[T]) { me.subscriberMapLock.Lock() defer me.subscriberMapLock.Unlock() // subscriberKey := subscriberKey[T](wd, subscriber) if sub, ok := me.subscriberMap[subscriberKey]; ok { me.et.Unsubscribe(wd.(*world).world, sub) delete(me.subscriberMap, subscriberKey) } } // 发布该类型的事件 func (me *EventType[T]) publish(wd World, event *T) { me.et.Publish(wd.(*world).world, *event) } func subscriberKey[T any](wd World, subscriber Subscriber[T]) string { wdSubscriberPointer := reflect.ValueOf(subscriber).Pointer() subscriberKey := fmt.Sprintf("%d-%d", wd.Id(), wdSubscriberPointer) return subscriberKey }