aboutsummaryrefslogtreecommitdiff
path: root/internal/game/tick.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/tick.go')
-rw-r--r--internal/game/tick.go31
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() {