refactor event systems
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
.devres/
|
||||
.idea/
|
||||
.failed_packets/
|
||||
tools/.*/
|
||||
+5
-1
@@ -46,7 +46,11 @@ func (s *LoginClient) OnCycle(_ event.Tick) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (s *LoginClient) OnStart(_ event.OnStart) (err error) {
|
||||
func (s *LoginClient) OnClose(_ event.Close) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (s *LoginClient) OnStart(_ event.Start) (err error) {
|
||||
if s.ServerHost == "" && s.ServerPort == 0 {
|
||||
var portStr string
|
||||
s.ServerHost, portStr, err = net.SplitHostPort(s.RemoteAddr().String())
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ func (s *StatusClient) Default(event any) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (s *StatusClient) OnStart(_ event.OnStart) (err error) {
|
||||
func (s *StatusClient) OnStart(_ event.Start) (err error) {
|
||||
parts := strings.Split(s.RemoteAddr().String(), ":")
|
||||
versionData, err := data.LookUpVersionByName(s.Version)
|
||||
if err != nil {
|
||||
|
||||
+21
-12
@@ -10,9 +10,8 @@ import (
|
||||
)
|
||||
|
||||
type Loop struct {
|
||||
HandlerFunctions map[reflect.Type][]reflect.Value
|
||||
handlerFunctions map[reflect.Type][]reflect.Value
|
||||
Handlers []any
|
||||
HandlerIndex int
|
||||
}
|
||||
|
||||
type Unhandled struct {
|
||||
@@ -24,7 +23,7 @@ type Anything struct {
|
||||
}
|
||||
|
||||
type (
|
||||
OnStart struct{}
|
||||
Start struct{}
|
||||
Tick struct{}
|
||||
)
|
||||
|
||||
@@ -33,6 +32,11 @@ type HandlerDoneErr struct {
|
||||
Return error
|
||||
}
|
||||
|
||||
// Close is fired when the loop shuts down.
|
||||
type Close struct {
|
||||
Reason error
|
||||
}
|
||||
|
||||
func (e HandlerDoneErr) Error() string {
|
||||
return "HandlerDoneErr"
|
||||
}
|
||||
@@ -43,10 +47,11 @@ func (e HandlerDoneErr) Unwrap() error {
|
||||
|
||||
// ErrDontForward will stop the event from being forwarded to other handlers, including anything handlers.
|
||||
var ErrDontForward = errors.New("dont forward")
|
||||
var WhileClosingErr = errors.New("error while closing")
|
||||
|
||||
// SetHandlerFunctions initializes and populates the HandlerFunctions map by reflecting over methods of registered handlers.
|
||||
func (l *Loop) SetHandlerFunctions() {
|
||||
l.HandlerFunctions = make(map[reflect.Type][]reflect.Value)
|
||||
// UpdateHandlerFunctions initializes and populates the handlerFunctions map by reflecting over methods of registered handlers.
|
||||
func (l *Loop) UpdateHandlerFunctions() {
|
||||
l.handlerFunctions = make(map[reflect.Type][]reflect.Value)
|
||||
for _, inst := range l.Handlers {
|
||||
t := reflect.TypeOf(inst)
|
||||
v := reflect.ValueOf(inst)
|
||||
@@ -54,14 +59,14 @@ func (l *Loop) SetHandlerFunctions() {
|
||||
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)
|
||||
slog.Warn("Invalid event handler signature", "at", t.String()+"."+method.Name)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
eventType := method.Type.In(1)
|
||||
l.HandlerFunctions[eventType] = append(l.HandlerFunctions[eventType], v.Method(i))
|
||||
l.handlerFunctions[eventType] = append(l.handlerFunctions[eventType], v.Method(i))
|
||||
slog.Debug("Registered Handler", "at", t.String()+"."+method.Name, "for", eventType.String())
|
||||
}
|
||||
}
|
||||
@@ -70,7 +75,7 @@ func (l *Loop) SetHandlerFunctions() {
|
||||
// FireFound triggers all handlers registered for the specified event type and returns if handlers were found or an error occurred.
|
||||
func (l *Loop) FireFound(event any) (found bool, err error) {
|
||||
var handlers []reflect.Value
|
||||
if handlers, found = l.HandlerFunctions[reflect.TypeOf(event)]; found {
|
||||
if handlers, found = l.handlerFunctions[reflect.TypeOf(event)]; found {
|
||||
for _, handler := range handlers {
|
||||
errV := handler.Call([]reflect.Value{reflect.ValueOf(event)})[0]
|
||||
if !errV.IsNil() {
|
||||
@@ -103,9 +108,9 @@ func (l *Loop) Fire(event any) (err error) {
|
||||
}
|
||||
|
||||
func (l *Loop) Start() (err error) {
|
||||
_ = *l // exit early on nil connection
|
||||
l.SetHandlerFunctions()
|
||||
err = l.Fire(OnStart{})
|
||||
_ = *l // exit early on nil loop
|
||||
l.UpdateHandlerFunctions()
|
||||
err = l.Fire(Start{})
|
||||
for err == nil {
|
||||
err = l.Fire(Tick{})
|
||||
if err != nil {
|
||||
@@ -115,5 +120,9 @@ func (l *Loop) Start() (err error) {
|
||||
if errors.Is(err, HandlerDoneErr{}) {
|
||||
err = errors.Unwrap(err)
|
||||
}
|
||||
closeErr := l.Fire(Close{err})
|
||||
if closeErr != nil {
|
||||
err = errors.Join(err, errors.Join(WhileClosingErr, closeErr))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package event
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Stdin struct {
|
||||
Val string
|
||||
}
|
||||
|
||||
type StdinHandler struct {
|
||||
*Loop
|
||||
stdInChan chan Stdin
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func (s *StdinHandler) OnTick(_ Tick) (err error) {
|
||||
select {
|
||||
case stdin := <-s.stdInChan:
|
||||
err = s.Fire(Stdin{stdin.Val})
|
||||
default:
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *StdinHandler) ScanJob() {
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
select {
|
||||
case <-s.ctx.Done():
|
||||
return
|
||||
default:
|
||||
s.stdInChan <- Stdin{scanner.Text()}
|
||||
}
|
||||
}
|
||||
}
|
||||
func (s *StdinHandler) OnStart(_ Start) (err error) {
|
||||
s.stdInChan = make(chan Stdin)
|
||||
s.ctx, s.cancel = context.WithCancel(context.Background())
|
||||
go s.ScanJob()
|
||||
return
|
||||
}
|
||||
|
||||
func (s *StdinHandler) OnClose(_ Close) (err error) {
|
||||
s.cancel()
|
||||
return
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package client
|
||||
package event
|
||||
|
||||
import (
|
||||
"slices"
|
||||
+5
-5
@@ -17,7 +17,7 @@ var BadPacketTypeError = errors.New("bad packet type")
|
||||
var BadPacketIdError = errors.New("bad packet id")
|
||||
var PacketNotFullyDecodedError = errors.New("packet not fully decoded")
|
||||
|
||||
// UnCodablePacket represents a packet that could not be decoded due to proto_generated not supporting all packets.
|
||||
// UnCodablePacket represents a packet that could not be decoded.
|
||||
type UnCodablePacket struct {
|
||||
Err error
|
||||
Data []byte
|
||||
@@ -109,13 +109,13 @@ func (c *Conn) Receive() (packet proto_base.EncodeDecodeAble, err error) {
|
||||
if err != nil {
|
||||
packet = &UnCodablePacket{Err: err, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
if b.Len() != 0 {
|
||||
err = nil
|
||||
packet = &UnCodablePacket{Err: PacketNotFullyDecodedError, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
|
||||
return
|
||||
}
|
||||
//fmt.Println("recv:", packet)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -130,11 +130,11 @@ func (c *Conn) OnTick(_ event.Tick) (err error) {
|
||||
}
|
||||
|
||||
func (c *Conn) Start(handlers ...any) (err error) {
|
||||
if c.Loop == nil {
|
||||
c.Loop = &event.Loop{}
|
||||
c.Handlers = append(c.Handlers, c)
|
||||
}
|
||||
c.Handlers = []any{c}
|
||||
c.Handlers = append(c.Handlers, handlers...)
|
||||
err = c.Loop.Start()
|
||||
c.Handlers = c.Handlers[:len(c.Handlers)-len(handlers)]
|
||||
c.Loop.SetHandlerFunctions()
|
||||
return
|
||||
}
|
||||
|
||||
+1
-2
@@ -30,7 +30,7 @@ func (c *RawConn) SendRaw(rawPacketBytes []byte) (err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
zW := zlib.NewWriter(packetBuffer)
|
||||
zW := zlib.NewWriter(packetBuffer) // ignore we don't care about the result if it errors
|
||||
_, err = zW.Write(rawPacketBytes)
|
||||
if err != nil {
|
||||
return
|
||||
@@ -106,7 +106,6 @@ func (c *RawConn) ReceiveRaw() (packetBytes []byte, err error) {
|
||||
} else {
|
||||
packetBytes = rawPacketBytes
|
||||
}
|
||||
//fmt.Println("recv:", packetBytes)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ func (c *ConfigServer) Default(event event.Anything) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (c *ConfigServer) OnStart(_ event.OnStart) (err error) {
|
||||
func (c *ConfigServer) OnStart(_ event.Start) (err error) {
|
||||
n, err := data.LoadRegistry(c.Version)
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
@@ -116,7 +116,7 @@ func (l *LoginServer) OnDefault(event event.Unhandled) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (l *LoginServer) OnStart(_ event.OnStart) (err error) {
|
||||
func (l *LoginServer) OnStart(_ event.Start) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -124,6 +124,10 @@ func (l *LoginServer) OnCycle(_ event.Tick) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (s *LoginServer) OnClose(_ event.Close) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
type LoginServerSetting func(*LoginServer)
|
||||
|
||||
func WithOtherAccount(a *api.Account) LoginServerSetting {
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"math/rand/v2"
|
||||
"time"
|
||||
|
||||
"github.com/admin-else/strom/client"
|
||||
"github.com/admin-else/strom/data"
|
||||
"github.com/admin-else/strom/event"
|
||||
"github.com/admin-else/strom/proto"
|
||||
@@ -34,7 +33,7 @@ var StatusResponse = server.StatusResponse{
|
||||
|
||||
type Server struct {
|
||||
*proto.Conn
|
||||
*client.Timer
|
||||
*event.Timer
|
||||
MinCycle, MaxCycle, Current int32
|
||||
}
|
||||
|
||||
@@ -66,7 +65,7 @@ var voidChunk = &v1_21_8.PlayToClientPacketMapChunk{X: 3, Z: 3, Heightmaps: []st
|
||||
Data []int64
|
||||
}{Type: "motion_blocking", Data: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}, ChunkData: v1_21_8.ByteArray{Val: []uint8{0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39, 0x0, 0x0, 0x0, 0x0, 0x0, 0x39}}, BlockEntities: []v1_21_8.ChunkBlockEntity{}, SkyLightMask: []int64{}, BlockLightMask: []int64{}, EmptySkyLightMask: []int64{}, EmptyBlockLightMask: []int64{}, SkyLight: [][]uint8{}, BlockLight: [][]uint8{}}
|
||||
|
||||
func (s *Server) OnStart(_ event.OnStart) (err error) {
|
||||
func (s *Server) OnStart(_ event.Start) (err error) {
|
||||
//goland:noinspection GoResourceLeak captures the conn object which should NOT be closed
|
||||
playerData, err := server.ServeLogin(s.Conn, server.WithRawStatus(StatusResponse), server.WithCompatibleVersions(772))
|
||||
if err != nil {
|
||||
@@ -170,7 +169,7 @@ func main() {
|
||||
slog.SetLogLoggerLevel(slog.LevelInfo)
|
||||
err := server.StartServerWithFactory(":25565", func(c *proto.Conn) (h any, err error) {
|
||||
s := &Server{Conn: c, MinCycle: 8297, MaxCycle: 8304, Current: 8297}
|
||||
s.Timer = &client.Timer{}
|
||||
s.Timer = &event.Timer{}
|
||||
h = s
|
||||
return
|
||||
})
|
||||
|
||||
@@ -34,7 +34,7 @@ func (p *ProxyClient) OnCycle(_ event.Tick) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (p *ProxyClient) OnStart(_ event.OnStart) (err error) {
|
||||
func (p *ProxyClient) OnStart(_ event.Start) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ func (p *Proxy) OnCycle(_ event.Tick) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Proxy) OnStart(_ event.OnStart) (err error) {
|
||||
func (p *Proxy) OnStart(_ event.Start) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func SaveUnCodeAbleAsTest(d proto_base.Direction, packet *proto.UnCodablePacket)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("Error", packet.Err, "saved to", f.Name(), "data:", packet.Data)
|
||||
slog.Info("Packet failed to parse", "error", packet.Err, "saved", f.Name(), "data", fmt.Sprintf("%q", packet.Data))
|
||||
}
|
||||
|
||||
var StatusResponse = server.StatusResponse{
|
||||
|
||||
Reference in New Issue
Block a user