jl-ecs/events.go
walker 03669cd1b3 调整世界运行倍速实现方式
调整事件订阅发布接口
调整事件回调函数为待执行函数,世界添加执行接口(待考虑是否需要处理结果返回)
2023-09-21 09:41:49 +08:00

90 lines
2.2 KiB
Go

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)
)
// 开启底层事件处理调试
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)
}
// 发布该类型的事件
// 在world协程外执行
func (me *EventType[T]) Publish(wd World, event *T) {
wd.Execute(func() {
me.et.Publish(wd.(*world).world, *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 {
fn := func(w donburi.World, event T) {
subscriber(wd, event)
}
me.subscriberMap[subscriberKey] = fn
wd.Execute(func() {
me.et.Subscribe(wd.(*world).world, fn)
})
}
}
// 取消订阅该类型的事件
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 {
wd.Execute(func() {
me.et.Unsubscribe(wd.(*world).world, sub)
delete(me.subscriberMap, subscriberKey)
})
}
}
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
}