77 lines
1.5 KiB
Go
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
|
|
}
|