diff options
Diffstat (limited to 'internal/net')
| -rw-r--r-- | internal/net/server.go | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/internal/net/server.go b/internal/net/server.go index 11339d7..9da90ea 100644 --- a/internal/net/server.go +++ b/internal/net/server.go @@ -11,7 +11,9 @@ import ( "math/big" "net" "net/http" + "sort" "sync" + "sync/atomic" "time" "thehouseoficarus/internal/color" @@ -70,8 +72,22 @@ type Session struct { PendingUndigRoom int promptVisible bool writeMu sync.Mutex + + // seq is a monotonically increasing sequence number assigned when the + // session is added to a Hub. Hub.AllSessions and Hub.PlayersInRoom sort + // sessions by seq so per-tick consumers iterate players in a stable, + // registration order instead of Go's randomized map iteration order. + // Sessions constructed without being added (e.g. in tests) keep seq=0 + // and tie-break by map-append order, which is also deterministic. + seq uint64 } +// sessionSeq is the source of Session.seq values. It is incremented under the +// adding Hub's mutex, so no extra atomicity is needed for correctness; atomic +// access keeps the package-level default counter safe if Hub.Add is ever +// called concurrently across hubs (it isn't today, but this is defensive). +var sessionSeq atomic.Uint64 + type Server struct { config *config.Config telnetLn net.Listener @@ -106,6 +122,7 @@ func (h *Hub) OnRemove(cb func(*Session)) { func (h *Hub) Add(s *Session) { h.mu.Lock() defer h.mu.Unlock() + s.seq = sessionSeq.Add(1) h.sessions[s] = true } @@ -165,6 +182,7 @@ func (h *Hub) AllSessions() []*Session { for s := range h.sessions { out = append(out, s) } + sort.SliceStable(out, func(i, j int) bool { return out[i].seq < out[j].seq }) return out } @@ -177,6 +195,7 @@ func (h *Hub) PlayersInRoom(roomID int) []*Session { out = append(out, s) } } + sort.SliceStable(out, func(i, j int) bool { return out[i].seq < out[j].seq }) return out } |
