2024-01-26 00:29:05 +01:00

77 lines
1.5 KiB
Go

package game
import (
"net"
"sync"
"sync/atomic"
"time"
)
// PlayerManager keeps tracks of all players.
type PlayerManager struct {
players sync.Map
count atomic.Int64
}
// NewPlayerManager creates a new player manager.
func NewPlayerManager() *PlayerManager {
m := &PlayerManager{}
timeout := 5 * time.Second
interval := time.Second
go func() {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for range ticker.C {
now := time.Now()
m.players.Range(func(key, value interface{}) bool {
player := value.(*Player)
if !player.lastPacket.IsZero() && now.After(player.lastPacket.Add(timeout)) {
player.OnDisconnect()
m.players.Delete(key)
m.count.Add(-1)
}
return true
})
}
}()
return m
}
// Contains tells you whether the address is already a registered client.
func (m *PlayerManager) Contains(addr *net.UDPAddr) bool {
_, exists := m.players.Load(addr.String())
return exists
}
// Count returns the number of clients.
func (m *PlayerManager) Count() int {
return int(m.count.Load())
}
// Each calls the callback function for each client.
func (m *PlayerManager) Each(callback func(*Player) bool) {
m.players.Range(func(key, value any) bool {
return callback(value.(*Player))
})
}
// Get either returns a new or existing client for the requested address.
func (m *PlayerManager) Get(addr *net.UDPAddr) *Player {
obj, exists := m.players.Load(addr.String())
if exists {
return obj.(*Player)
}
client := NewClient(addr)
m.players.Store(addr.String(), client)
m.count.Add(1)
return client
}