diff options
| author | historia <[not public]> | 2026-09-16 21:35:55 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-09-16 21:35:55 -0400 |
| commit | fea2cc6839ec3ee17940a2dea69622dc6f4deabf (patch) | |
| tree | 9d893525ca20d2cc920e9e866f84f71b605d8ae9 /internal/net | |
| parent | 35ddd0ad2215760bb1d3dc7724480f179ea33fa6 (diff) | |
| download | thehouseoficarus-fea2cc6839ec3ee17940a2dea69622dc6f4deabf.tar.gz | |
fix: unify crafting ingredient resolution; fix superheat alternatives, quantity gates, and dropped combine byproducts
Diffstat (limited to 'internal/net')
| -rw-r--r-- | internal/net/server.go | 20 | ||||
| -rw-r--r-- | internal/net/web.go | 4 |
2 files changed, 17 insertions, 7 deletions
diff --git a/internal/net/server.go b/internal/net/server.go index 66d31e3..78eceb8 100644 --- a/internal/net/server.go +++ b/internal/net/server.go @@ -57,7 +57,7 @@ const ( type Session struct { Conn Conn - State SessionState + state atomic.Int32 Account *player.Account Player *player.Player PendingChar string @@ -116,6 +116,16 @@ type Session struct { seq uint64 } +// State returns the session's current protocol state. Safe on any +// goroutine: the owner writes the state while connection goroutines read +// it in the HandleSessionOnOwner dispatch, so a plain field was a data +// race (reproduced by the logout-countdown input regression test). +func (sess *Session) State() SessionState { return SessionState(sess.state.Load()) } + +// SetState transitions the session to a new protocol state. +// Owner goroutine only. +func (sess *Session) SetState(s SessionState) { sess.state.Store(int32(s)) } + // SetAuthName records the account name offered for password entry. // Owner goroutine only. func (sess *Session) SetAuthName(name string) { @@ -598,9 +608,9 @@ func (s *Server) serveTelnet() { return } sess := &Session{ - Conn: newTCPConn(conn), - State: StateAccountName, + Conn: newTCPConn(conn), } + sess.SetState(StateAccountName) // Queued writes like the websocket transport: a dedicated writer // goroutine performs the I/O with per-message deadlines, so a slow // or stalled telnet client can never block game code. @@ -621,9 +631,9 @@ func (s *Server) serveTelnetTLS() { return } sess := &Session{ - Conn: newTCPConn(conn), - State: StateAccountName, + Conn: newTCPConn(conn), } + sess.SetState(StateAccountName) sess.StartWriter() s.hub.Add(sess) go s.handleSession(sess, s.handler) diff --git a/internal/net/web.go b/internal/net/web.go index 233928f..8353c8d 100644 --- a/internal/net/web.go +++ b/internal/net/web.go @@ -61,9 +61,9 @@ func newHTTPMux(s *Server) *http.ServeMux { return } sess := &Session{ - Conn: newWSConn(ws), - State: StateAccountName, + Conn: newWSConn(ws), } + sess.SetState(StateAccountName) sess.StartWriter() s.hub.Add(sess) go s.handleSession(sess, s.handler) |
