diff --git a/data/item.go b/data/item.go index 51e247e..11e58bd 100644 --- a/data/item.go +++ b/data/item.go @@ -1,5 +1,7 @@ package data +import "sync" + // { // "id": 2, // "name": "granite", @@ -15,15 +17,21 @@ type Item struct { } var ItemsCache = make(map[string][]*Item) +var ItemsCacheMutex = &sync.RWMutex{} func ItemsForVersion(v string) (ret []*Item) { var ok bool + ItemsCacheMutex.RLock() if ret, ok = ItemsCache[v]; ok { + ItemsCacheMutex.RUnlock() return } + ItemsCacheMutex.RUnlock() var b []*Item must(LoadVersionedJson(v, "items", &b)) + ItemsCacheMutex.Lock() ItemsCache[v] = b + ItemsCacheMutex.Unlock() return b } diff --git a/event/event_bus.go b/event/event_bus.go index 8091261..3f275bb 100644 --- a/event/event_bus.go +++ b/event/event_bus.go @@ -35,16 +35,16 @@ type ( Tick struct{} ) -// HandlerDoneErr will stop the event loop and return the error if provided. -type HandlerDoneErr struct { - Return error -} - // Close is fired when the loop shuts down. type Close struct { Reason error } +// HandlerDoneErr will stop the event loop and return the error if provided. +type HandlerDoneErr struct { + Return error +} + func (e HandlerDoneErr) Error() string { return "HandlerDoneErr" } @@ -53,12 +53,26 @@ func (e HandlerDoneErr) Unwrap() error { return e.Return } +// MainHandlerErr is a special error used to tell the event loop that the main loop has exited +type MainHandlerErr struct { + Return error +} + +func (e MainHandlerErr) Error() string { + return "MainHandlerErr" +} + +func (e MainHandlerErr) Unwrap() error { + return e.Return +} + // DontForwardErr will stop the event from being forwarded to other handlers, including anything handlers. var DontForwardErr = errors.New("dont forward") var WhileClosingErr = errors.New("error while closing") // CloseNonCriticalErr will close even when the event is non-critical var CloseNonCriticalErr = errors.New("close non-critical") +var ContextDoneErr = errors.New("context done") func ValidateHandler(h any) (eventType reflect.Type, hv reflect.Value) { hv = reflect.ValueOf(h) @@ -146,6 +160,15 @@ func (l *Loop) Fire(event any) (err error) { return } +func (l *Loop) OnTick(_ Tick) (err error) { + select { + case <-l.Ctx.Done(): + err = ContextDoneErr + default: + } + return +} + func (l *Loop) startLoop() (err error) { _ = *l // exit early on nil loop for { @@ -168,10 +191,17 @@ func (l *Loop) startLoop() (err error) { func (l *Loop) StartLoop() (err error) { go func() { - l.ErrChan <- l.startLoop() + l.ErrChan <- MainHandlerErr{l.startLoop()} }() err = <-l.ErrChan l.cancel() + errMaybe := MainHandlerErr{} + if errors.As(err, &errMaybe) { + err = errors.Unwrap(err) + } else { + for !errors.Is(<-l.ErrChan, MainHandlerErr{}) { + } + } return } diff --git a/proto/connection.go b/proto/connection.go index cbccc45..1a391f6 100644 --- a/proto/connection.go +++ b/proto/connection.go @@ -19,7 +19,6 @@ var ( BadPacketTypeErr = errors.New("bad packet type") BadPacketIdErr = errors.New("bad packet id") PacketNotFullyDecodedErr = errors.New("packet not fully decoded") - ContextDoneErr = errors.New("context done") WrongStateErr = errors.New("wrong state") WrongDirectionErr = errors.New("wrong direction") CantTranslateErr = errors.New("cant translate packet") @@ -224,9 +223,6 @@ func (c *Conn) OnTick(_ event.Tick) (err error) { case packet = <-c.packetCh: slog.Debug("receive", "actor", c.Actor, "packet", fmt.Sprintf("%#v", packet)) err = c.Loop.Fire(packet) - case <-c.Ctx.Done(): - err = ContextDoneErr - return default: } } else {