119 lines
2.6 KiB
Go
119 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"math/rand/v2"
|
|
"strconv"
|
|
)
|
|
|
|
type Game struct {
|
|
players map[uint]*Player
|
|
hosts map[*Host]bool
|
|
|
|
playerToken uint64 // Verification token for players
|
|
hostToken uint64 // Verification token for the host
|
|
|
|
registerPlayer chan *Player // Register requests from players.
|
|
unregisterPlayer chan *Player // Unregister requests from players.
|
|
registerHost chan *Host // Register requests from hosts.
|
|
unregisterHost chan *Host // Unregister requests from hosts.
|
|
|
|
activePlayer *Player
|
|
}
|
|
|
|
func tokenize(token uint64) string {
|
|
return strconv.FormatUint(token, 36)
|
|
}
|
|
|
|
func newGame() *Game {
|
|
return &Game{
|
|
players: make(map[uint]*Player),
|
|
hosts: make(map[*Host]bool),
|
|
|
|
playerToken: rand.Uint64(),
|
|
hostToken: rand.Uint64(),
|
|
|
|
registerPlayer: make(chan *Player),
|
|
unregisterPlayer: make(chan *Player),
|
|
registerHost: make(chan *Host),
|
|
unregisterHost: make(chan *Host),
|
|
}
|
|
}
|
|
|
|
func (g *Game) checkPlayerToken(token string) bool {
|
|
return token == tokenize(g.playerToken)
|
|
}
|
|
|
|
func (g *Game) broadcastHosts(message []byte) {
|
|
for client := range g.hosts {
|
|
if !client.send(message) {
|
|
delete(g.hosts, client)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (g *Game) broadcastPlayers(message []byte) {
|
|
for id := range g.players {
|
|
g.sendTo(id, message)
|
|
}
|
|
}
|
|
|
|
func (g *Game) sendTo(playerId uint, message []byte) error {
|
|
client, ok := g.players[playerId]
|
|
if !ok {
|
|
return fmt.Errorf("No Player %d", playerId)
|
|
}
|
|
|
|
if !client.send(message) {
|
|
delete(g.players, playerId)
|
|
return fmt.Errorf("Player %d disconnected", playerId)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (g *Game) run() {
|
|
for {
|
|
select {
|
|
|
|
case player := <-g.registerPlayer:
|
|
g.players[player.Id] = player
|
|
log.Printf("Player %d (%s: %s) registered", player.Id, player.Team, player.Name)
|
|
join := makeMessage("join", player)
|
|
g.broadcastHosts(join)
|
|
|
|
case player := <-g.unregisterPlayer:
|
|
id := player.Id
|
|
if _, ok := g.players[id]; ok {
|
|
delete(g.players, id)
|
|
player.closeQueue()
|
|
}
|
|
log.Printf("Player %d (%s: %s) left", player.Id, player.Team, player.Name)
|
|
join := makeMessage("part", player)
|
|
g.broadcastHosts(join)
|
|
|
|
case host := <-g.registerHost:
|
|
g.hosts[host] = true
|
|
log.Println("Host joined")
|
|
for _, player := range g.players {
|
|
join := makeMessage("join", player)
|
|
g.broadcastHosts(join)
|
|
}
|
|
|
|
case host := <-g.unregisterHost:
|
|
if _, ok := g.hosts[host]; ok {
|
|
delete(g.hosts, host)
|
|
host.closeQueue()
|
|
}
|
|
log.Println("Host left")
|
|
}
|
|
}
|
|
}
|
|
|
|
func (g *Game) reveal(value bool) {
|
|
log.Printf("Revealing %v!", value)
|
|
reveal := makeMessage("reveal", value)
|
|
g.broadcastHosts(reveal)
|
|
}
|