only create games when match is joined, remove old players from queue

This commit is contained in:
stryan 2021-09-29 14:51:58 -04:00
parent f5eac37b06
commit deb6d24282
2 changed files with 41 additions and 13 deletions

View File

@ -5,6 +5,7 @@ import (
"sync" "sync"
"time" "time"
"git.saintnet.tech/stryan/snengame/internal/game"
"github.com/google/uuid" "github.com/google/uuid"
) )
@ -12,6 +13,7 @@ type Coordinator struct {
Matches map[uuid.UUID]*Session Matches map[uuid.UUID]*Session
MatchLock *sync.Mutex MatchLock *sync.Mutex
PlayerQueueChan chan uuid.UUID PlayerQueueChan chan uuid.UUID
PlayerPool map[MMRPlayer]bool
CallbackChan map[uuid.UUID]chan uuid.UUID CallbackChan map[uuid.UUID]chan uuid.UUID
} }
@ -20,6 +22,7 @@ func NewCoordinator() *Coordinator {
Matches: make(map[uuid.UUID]*Session), Matches: make(map[uuid.UUID]*Session),
MatchLock: &sync.Mutex{}, MatchLock: &sync.Mutex{},
PlayerQueueChan: make(chan uuid.UUID), PlayerQueueChan: make(chan uuid.UUID),
PlayerPool: make(map[MMRPlayer]bool),
CallbackChan: make(map[uuid.UUID]chan uuid.UUID), CallbackChan: make(map[uuid.UUID]chan uuid.UUID),
} }
} }
@ -27,6 +30,7 @@ func NewCoordinator() *Coordinator {
func (c *Coordinator) Start() { func (c *Coordinator) Start() {
go MatchMaker(c) go MatchMaker(c)
go MatchCleaner(c) go MatchCleaner(c)
go QueueCleaner(c)
} }
func (c *Coordinator) Coordinate(cmd *SessionCommand) *SessionCommandResult { func (c *Coordinator) Coordinate(cmd *SessionCommand) *SessionCommandResult {
@ -60,6 +64,11 @@ func (c *Coordinator) Coordinate(cmd *SessionCommand) *SessionCommandResult {
} }
} }
resp := m.Join(cmd.ID) resp := m.Join(cmd.ID)
if m.p1 != uuid.Nil && m.p2 != uuid.Nil {
log.Printf("Starting game for %v and %v\n", m.p1, m.p2)
m.Game = game.NewGame()
m.Active = true
}
return &SessionCommandResult{ return &SessionCommandResult{
ID: cmd.ID, ID: cmd.ID,
MatchID: m.ID, MatchID: m.ID,

View File

@ -8,41 +8,48 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
) )
type MMRPlayer struct {
Id uuid.UUID
MMR int
QueueTime time.Time
}
func MatchMaker(c *Coordinator) { func MatchMaker(c *Coordinator) {
//in the future the int below will be MMR or something, but for now it's just a set //in the future the int will be MMR or something, but for now it's just a set
pool := make(map[uuid.UUID]int)
for { for {
select { select {
case p := <-c.PlayerQueueChan: case p := <-c.PlayerQueueChan:
//add player to pool //add player to pool
pool[p] = 0 c.PlayerPool[MMRPlayer{
Id: p,
MMR: 0,
QueueTime: time.Now()}] = true
log.Printf("Player %v has queued", p) log.Printf("Player %v has queued", p)
default: default:
//no new players, let's try to matchmake //no new players, let's try to matchmake
if len(pool) < 2 { if len(c.PlayerPool) < 2 {
continue continue
} else { } else {
//fancy matchmaking math to guarantee a fair game //fancy matchmaking math to guarantee a fair game
var p1, p2 uuid.UUID var p1, p2 MMRPlayer
for key, _ := range pool { for key, _ := range c.PlayerPool {
p1 = key p1 = key
break break
} }
delete(pool, p1) delete(c.PlayerPool, p1)
for key, _ := range pool { for key, _ := range c.PlayerPool {
p2 = key p2 = key
break break
} }
delete(pool, p2) delete(c.PlayerPool, p2)
m := NewSession() m := NewSession()
log.Printf("Creating match %v for %v and %v", m.ID, p1, p2) log.Printf("Creating match %v for %v and %v", m.ID, p1, p2)
m.Active = true m.Active = false
m.Game = game.NewGame()
c.MatchLock.Lock() c.MatchLock.Lock()
c.Matches[m.ID] = m c.Matches[m.ID] = m
c.MatchLock.Unlock() c.MatchLock.Unlock()
c.CallbackChan[p1] <- m.ID c.CallbackChan[p1.Id] <- m.ID
c.CallbackChan[p2] <- m.ID c.CallbackChan[p2.Id] <- m.ID
go MatchWatcher(m) go MatchWatcher(m)
} }
@ -50,6 +57,18 @@ func MatchMaker(c *Coordinator) {
} }
} }
func QueueCleaner(c *Coordinator) {
for {
time.Sleep(5 * time.Minute)
for v, _ := range c.PlayerPool {
if time.Now().After(v.QueueTime.Add(time.Minute * 5)) {
log.Printf("Removing player %v from pool", v.Id)
delete(c.PlayerPool, v) //probably should just flag
}
}
}
}
func MatchCleaner(c *Coordinator) { func MatchCleaner(c *Coordinator) {
for { for {
time.Sleep(10 * time.Second) time.Sleep(10 * time.Second)