shotgun/lobby/match.go

71 lines
1.6 KiB
Go

package lobby
import (
"context"
"git.sunturtle.xyz/studio/shotgun/player"
"github.com/google/uuid"
)
type match struct {
dealer player.ID
chall chan player.ID
match chan GameID
}
// Queue waits for a match.
// This may cause a new match to be created.
func (l *Lobby) Queue(ctx context.Context, p player.ID) GameID {
select {
case <-ctx.Done():
return GameID{}
case m := <-l.matches:
// We found a dealer waiting for a match.
// We don't need to check the context here because the challenger
// channel is buffered and we have exclusive send access on it.
m.chall <- p
// We do need to check the context here in case they disappeared.
select {
case <-ctx.Done():
return GameID{}
case id := <-m.match:
return id
}
default: // do nothing
}
// We're a new dealer.
m := match{
dealer: p,
chall: make(chan player.ID, 1),
match: make(chan GameID, 1),
}
select {
case <-ctx.Done():
return GameID{}
case l.matches <- m:
// Our match is submitted. Move on.
case m := <-l.matches:
// We might have become a dealer at the same time someone else did.
// We created our match, but we can try to get theirs as well and
// never send ours, since l.matches is unbuffered.
m.chall <- p
select {
case <-ctx.Done():
return GameID{}
case id := <-m.match:
return id
}
}
select {
case <-ctx.Done():
return GameID{}
case chall := <-m.chall:
// Got our challenger. Create the game and send the ID back.
id := uuid.New()
l.Start(id, p, chall)
// Don't need to check context because the match channel is buffered.
m.match <- id
return id
}
}