refactor event handling to support multiple handlers and improve default behavior
This commit is contained in:
+40
-22
@@ -2,11 +2,13 @@ package event
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HandlerInst interface {
|
type Default struct {
|
||||||
Default(event any) (err error)
|
Val any
|
||||||
}
|
}
|
||||||
|
|
||||||
type OnStart struct{}
|
type OnStart struct{}
|
||||||
@@ -14,32 +16,48 @@ type OnLoopCycle struct{}
|
|||||||
|
|
||||||
var HandlerDone = errors.New("handler done")
|
var HandlerDone = errors.New("handler done")
|
||||||
|
|
||||||
func FindHandlers(inst HandlerInst) (handlers map[reflect.Type]reflect.Value) {
|
func FindHandlers(insts []any) (handlers map[reflect.Type][]reflect.Value) {
|
||||||
handlers = make(map[reflect.Type]reflect.Value)
|
handlers = make(map[reflect.Type][]reflect.Value)
|
||||||
t := reflect.TypeOf(inst)
|
for _, inst := range insts {
|
||||||
v := reflect.ValueOf(inst)
|
t := reflect.TypeOf(inst)
|
||||||
for i := 0; i < t.NumMethod(); i++ {
|
v := reflect.ValueOf(inst)
|
||||||
method := t.Method(i)
|
for i := 0; i < t.NumMethod(); i++ {
|
||||||
if method.Type.NumIn() != 2 || method.Type.NumOut() != 1 {
|
method := t.Method(i)
|
||||||
continue
|
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:", method.Name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
eventType := method.Type.In(1)
|
||||||
|
handlers[eventType] = append(handlers[eventType], v.Method(i))
|
||||||
}
|
}
|
||||||
if method.Type.Out(0) != reflect.TypeFor[error]() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
eventType := method.Type.In(1)
|
|
||||||
handlers[eventType] = v.Method(i)
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Fire(inst HandlerInst, event any, handlers map[reflect.Type]reflect.Value) (err error) {
|
func FireFound(event any, handlersMap map[reflect.Type][]reflect.Value) (found bool, err error) {
|
||||||
if handler, ok := handlers[reflect.TypeOf(event)]; ok {
|
var handlers []reflect.Value
|
||||||
errV := handler.Call([]reflect.Value{reflect.ValueOf(event)})[0]
|
if handlers, found = handlersMap[reflect.TypeOf(event)]; found {
|
||||||
if !errV.IsNil() {
|
for _, handler := range handlers {
|
||||||
err = errV.Interface().(error)
|
errV := handler.Call([]reflect.Value{reflect.ValueOf(event)})[0]
|
||||||
|
if !errV.IsNil() {
|
||||||
|
err = errV.Interface().(error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
err = inst.Default(event)
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-5
@@ -129,21 +129,25 @@ func (c *Conn) Receive() (packet any, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) Start(inst event.HandlerInst) (err error) {
|
func (c *Conn) StartOne(inst any) (err error) {
|
||||||
|
return c.Start([]any{inst})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) Start(insts []any) (err error) {
|
||||||
_ = *c // exit early on nil connection
|
_ = *c // exit early on nil connection
|
||||||
handlers := event.FindHandlers(inst)
|
handlers := event.FindHandlers(insts)
|
||||||
err = event.Fire(inst, event.OnStart{}, handlers)
|
err = event.Fire(event.OnStart{}, handlers)
|
||||||
for err == nil {
|
for err == nil {
|
||||||
var packet any
|
var packet any
|
||||||
packet, err = c.Receive()
|
packet, err = c.Receive()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = event.Fire(inst, packet, handlers)
|
err = event.Fire(packet, handlers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
err = event.Fire(inst, event.OnLoopCycle{}, handlers)
|
err = event.Fire(event.OnLoopCycle{}, handlers)
|
||||||
}
|
}
|
||||||
if errors.Is(err, event.HandlerDone) {
|
if errors.Is(err, event.HandlerDone) {
|
||||||
err = nil
|
err = nil
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package v1_21_8
|
package v1_21_8
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/admin-else/strom/proto_base"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/admin-else/strom/proto_base"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandshakingToServerPacketIdentifierToType(s string) (t any) {
|
func HandshakingToServerPacketIdentifierToType(s string) (t any) {
|
||||||
|
|||||||
Reference in New Issue
Block a user