66 lines
1.5 KiB
Go
66 lines
1.5 KiB
Go
package event
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
type Default struct {
|
|
Val any
|
|
}
|
|
|
|
type OnStart struct{}
|
|
type OnLoopCycle struct{}
|
|
|
|
var HandlerDone = errors.New("handler done")
|
|
|
|
func FindHandlers(insts []any) (handlers map[reflect.Type][]reflect.Value) {
|
|
handlers = make(map[reflect.Type][]reflect.Value)
|
|
for _, inst := range insts {
|
|
t := reflect.TypeOf(inst)
|
|
v := reflect.ValueOf(inst)
|
|
for i := 0; i < t.NumMethod(); i++ {
|
|
method := t.Method(i)
|
|
if strings.HasPrefix(method.Name, "On") {
|
|
if method.Type.NumIn() != 2 || method.Type.NumOut() != 1 || method.Type.Out(0) != reflect.TypeFor[error]() {
|
|
fmt.Println("Invalid event handler signature:", t.String(), ".", method.Name)
|
|
continue
|
|
}
|
|
} else {
|
|
continue
|
|
}
|
|
eventType := method.Type.In(1)
|
|
handlers[eventType] = append(handlers[eventType], v.Method(i))
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func FireFound(event any, handlersMap map[reflect.Type][]reflect.Value) (found bool, err error) {
|
|
var handlers []reflect.Value
|
|
if handlers, found = handlersMap[reflect.TypeOf(event)]; found {
|
|
for _, handler := range handlers {
|
|
errV := handler.Call([]reflect.Value{reflect.ValueOf(event)})[0]
|
|
if !errV.IsNil() {
|
|
err = errV.Interface().(error)
|
|
err = errors.Join(err, fmt.Errorf("event handler failed: at "))
|
|
return
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func Fire(event any, handlersMap map[reflect.Type][]reflect.Value) (err error) {
|
|
found, err := FireFound(event, handlersMap)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if !found {
|
|
_, err = FireFound(Default{event}, handlersMap)
|
|
}
|
|
return
|
|
}
|