aboutsummaryrefslogtreecommitdiff
path: root/internal/net
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-16 21:35:55 -0400
committerhistoria <[not public]>2026-09-16 21:35:55 -0400
commitfea2cc6839ec3ee17940a2dea69622dc6f4deabf (patch)
tree9d893525ca20d2cc920e9e866f84f71b605d8ae9 /internal/net
parent35ddd0ad2215760bb1d3dc7724480f179ea33fa6 (diff)
downloadthehouseoficarus-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.go20
-rw-r--r--internal/net/web.go4
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)