start labor on server part of server
This commit is contained in:
parent
6406997282
commit
2b9e617c10
5
go.mod
5
go.mod
@ -2,4 +2,7 @@ module git.sunturtle.xyz/studio/shotgun
|
|||||||
|
|
||||||
go 1.21.6
|
go 1.21.6
|
||||||
|
|
||||||
require github.com/google/uuid v1.5.0
|
require (
|
||||||
|
github.com/google/uuid v1.5.0
|
||||||
|
nhooyr.io/websocket v1.8.10
|
||||||
|
)
|
||||||
|
2
go.sum
2
go.sum
@ -1,2 +1,4 @@
|
|||||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q=
|
||||||
|
nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
|
||||||
|
88
server.go
Normal file
88
server.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"nhooyr.io/websocket"
|
||||||
|
|
||||||
|
"git.sunturtle.xyz/studio/shotgun/lobby"
|
||||||
|
"git.sunturtle.xyz/studio/shotgun/player"
|
||||||
|
"git.sunturtle.xyz/studio/shotgun/serve"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
l *lobby.Lobby
|
||||||
|
mu sync.Mutex
|
||||||
|
rooms map[lobby.GameID]*room
|
||||||
|
}
|
||||||
|
|
||||||
|
type room struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
pp []person
|
||||||
|
// NOTE(zeph): since only the players can ever see revealed shells, we
|
||||||
|
// could factor out the players into separate fields to save work on
|
||||||
|
// generating dtos for observers. hold that idea until it's needed.
|
||||||
|
}
|
||||||
|
|
||||||
|
type person struct {
|
||||||
|
conn *websocket.Conn
|
||||||
|
id player.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) room(id serve.GameID) *room {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
return s.rooms[id]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) join(id serve.GameID, p person) {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
r := s.rooms[id]
|
||||||
|
if r == nil {
|
||||||
|
r = &room{}
|
||||||
|
s.rooms[id] = r
|
||||||
|
}
|
||||||
|
r.pp = append(r.pp, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) close(id serve.GameID) {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
delete(s.rooms, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queue connects players to games. The connection immediately upgrades.
|
||||||
|
// This handler MUST be wrapped in [serve.WithPlayerID].
|
||||||
|
func (s *Server) Queue(w http.ResponseWriter, r *http.Request) {
|
||||||
|
p := serve.PlayerID(r.Context())
|
||||||
|
if p == (player.ID{}) {
|
||||||
|
panic("missing player ID")
|
||||||
|
}
|
||||||
|
conn, err := websocket.Accept(w, r, nil)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
person := person{conn: conn, id: p}
|
||||||
|
go s.joinAndServe(person)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) joinAndServe(p person) {
|
||||||
|
ctx, stop := context.WithTimeoutCause(context.Background(), 10*time.Minute, errQueueEmpty)
|
||||||
|
game := s.l.Queue(ctx, p.id)
|
||||||
|
stop()
|
||||||
|
if game == (lobby.GameID{}) {
|
||||||
|
// Context canceled.
|
||||||
|
p.conn.Close(websocket.StatusNormalClosure, "sorry, queue is empty...")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.join(game, p)
|
||||||
|
// TODO(zeph): need to broadcast to observers, need to listen for updates in a single goroutine, ...
|
||||||
|
}
|
||||||
|
|
||||||
|
var errQueueEmpty = errors.New("sorry, queue is empty")
|
Loading…
Reference in New Issue
Block a user