diff options
Diffstat (limited to 'internal/game/tick.go')
| -rw-r--r-- | internal/game/tick.go | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/internal/game/tick.go b/internal/game/tick.go index 4181622..ef8089a 100644 --- a/internal/game/tick.go +++ b/internal/game/tick.go @@ -16,19 +16,18 @@ import ( // lockout) forever. const disconnectCombatGraceTicks = 5 -// disconnectCombatDeferrals counts, per session, how many ticks its pending -// disconnect has already been deferred for combat. DisconnectTick is its only -// reader/writer and every tick system runs on the owner goroutine, so the map -// needs no lock. An entry is dropped when this path completes the hard remove; -// a session hard-removed elsewhere (a second Hub.Remove, shutdown) leaves at -// most one stale int behind. -var disconnectCombatDeferrals = map[*net.Session]int{} - func (g *Game) DisconnectTick() { if g.Hub == nil { return } - for _, sess := range g.Hub.AllSessions() { + // Lazy init: tests construct Game literals directly rather than via New. + if g.disconnectDeferrals == nil { + g.disconnectDeferrals = make(map[*net.Session]int) + } + sessions := g.Hub.AllSessions() + seen := make(map[*net.Session]bool, len(sessions)) + for _, sess := range sessions { + seen[sess] = true if !sess.IsDisconnecting() { continue } @@ -44,18 +43,26 @@ func (g *Game) DisconnectTick() { // until a restart. Defer while the fight can still resolve, but only // for a bounded grace period, then let the countdown proceed. if g.Combat.Get(p.Name) != nil { - if deferred := disconnectCombatDeferrals[sess]; deferred < disconnectCombatGraceTicks { - disconnectCombatDeferrals[sess] = deferred + 1 + if deferred := g.disconnectDeferrals[sess]; deferred < disconnectCombatGraceTicks { + g.disconnectDeferrals[sess] = deferred + 1 continue } } if sess.TickDisconnectCountdown() { - delete(disconnectCombatDeferrals, sess) + delete(g.disconnectDeferrals, sess) g.restoreGodPlayer(p) g.saveCharacter(p) g.Hub.HardRemove(sess) } } + // Drop counters for sessions hard-removed elsewhere (a second Hub.Remove, + // shutdown) so a departed session (and its Player) cannot be retained for + // the life of the process. + for sess := range g.disconnectDeferrals { + if !seen[sess] { + delete(g.disconnectDeferrals, sess) + } + } } func (g *Game) RegenTick() { |
