diff --git a/game.go b/game.go index 5899736..cf2ac03 100644 --- a/game.go +++ b/game.go @@ -1,15 +1,17 @@ package main import ( + "fmt" "time" ) type Game struct { - id Id - start time.Time - end time.Time - winner string - winMethod string + id Id + start time.Time + end time.Time + winner string + winMethod string + connections map[*Connection]bool } func gamesTable() { @@ -27,8 +29,9 @@ func gamesTable() { func NewGame() *Game { game := &Game{ - id: NewId(), - start: time.Now(), + id: NewId(), + start: time.Now(), + connections: make(map[*Connection]bool, 32), } if err := game.Create(); err != nil { log_error("%v", err) @@ -45,3 +48,48 @@ func (g *Game) Create() error { ;`, g.id.String(), g.start) return err } + +func (g *Game) Store() error { + _, err := db.Exec(` + update games + set end = ?, winner = ?, win_method = ? + where id = ? + ;`, g.end, g.winner, g.winMethod, g.id) + return err +} + +func (g *Game) Join(conn *Connection) { + g.connections[conn] = true +} + +func (g *Game) Quit(conn *Connection) { + delete(g.connections, conn) +} + +func (g *Game) Win(winner *Connection, method string) { + g.end = time.Now() + g.winner = winner.PlayerName() + g.winMethod = method + g.Store() + + for conn, _ := range g.connections { + fmt.Fprintf(conn, "player %s has won by %s victory.\n", winner.PlayerName(), method) + fmt.Fprintf(conn, "starting new game ...\n") + conn.Reset() + } + + ResetQueue() + + g.Reset() + + for conn, _ := range g.connections { + conn.Respawn() + } +} + +func (g *Game) Reset() { + connections := g.connections + fresh := NewGame() + *g = *fresh + g.connections = connections +} diff --git a/main.go b/main.go index 6f26e4c..b3fcd05 100644 --- a/main.go +++ b/main.go @@ -39,17 +39,7 @@ func handleConnection(conn *Connection) { defer conn.Close() conn.Login() - system, err := randomSystem() - if err != nil { - log_error("player %s failed to get random system: %v", conn.PlayerName(), err) - return - } - system.Arrive(conn) - if system.planets == 1 { - fmt.Fprintf(conn, "you are in the system %s. There is %d planet here.\n", system.name, system.planets) - } else { - fmt.Fprintf(conn, "you are in the system %s. There are %d planets here.\n", system.name, system.planets) - } + conn.Respawn() for { line, err := conn.ReadString('\n') switch err { diff --git a/session.go b/session.go index 2339e3c..1124c3d 100644 --- a/session.go +++ b/session.go @@ -9,8 +9,6 @@ import ( "time" ) -var connected = make(map[*Connection]bool, 32) - type Connection struct { net.Conn *bufio.Reader @@ -32,10 +30,19 @@ func NewConnection(conn net.Conn) *Connection { Reader: bufio.NewReader(conn), bombs: 1, } - connected[c] = true + currentGame.Join(c) return c } +func (conn *Connection) Reset() { + *conn = Connection{ + Conn: conn.Conn, + Reader: bufio.NewReader(conn.Conn), + bombs: 1, + } + currentGame.Join(conn) +} + func (c *Connection) Login() { for { fmt.Fprintf(c, "what is your name, adventurer?\n") @@ -79,8 +86,11 @@ func (c *Connection) System() *System { func (c *Connection) Close() error { log_info("player disconnecting: %s", c.PlayerName()) - delete(connected, c) - return c.Conn.Close() + currentGame.Quit(c) + if c.Conn != nil { + return c.Conn.Close() + } + return nil } func (c *Connection) PlayerName() string { @@ -168,10 +178,7 @@ func (c *Connection) Deposit(n int64) { } func (c *Connection) Win(method string) { - for conn, _ := range connected { - fmt.Fprintf(conn, "player %s has won.\n", c.PlayerName()) - conn.Close() - } + currentGame.Win(c, method) } func (c *Connection) Die() { diff --git a/system.go b/system.go index 0fefd58..8cb5a67 100644 --- a/system.go +++ b/system.go @@ -24,13 +24,18 @@ type System struct { colonizedBy *Connection } -func (s *System) Arrive(p *Connection) { - p.SetSystem(s) - log_info("player %s has arrived at system %s", p.PlayerName(), s.name) +func (s *System) Arrive(conn *Connection) { + conn.SetSystem(s) + log_info("player %s has arrived at system %s", conn.PlayerName(), s.name) if s.players == nil { s.players = make(map[*Connection]bool, 8) } - s.players[p] = true + s.players[conn] = true + if s.planets == 1 { + fmt.Fprintf(conn, "you are in the system %s. There is %d planet here.\n", s.name, s.planets) + } else { + fmt.Fprintf(conn, "you are in the system %s. There are %d planets here.\n", s.name, s.planets) + } } func (s *System) Leave(p *Connection) { diff --git a/work.go b/work.go index 942c1f8..f3bd0eb 100644 --- a/work.go +++ b/work.go @@ -2,10 +2,14 @@ package main import ( "container/heap" + "sync" "time" ) -var queue = make(Queue, 0, 32) +var ( + queue = make(Queue, 0, 32) + queueLock sync.Mutex +) type Future struct { ts time.Time @@ -59,7 +63,9 @@ func RunQueue() { time.Sleep(10 * time.Microsecond) continue } + queueLock.Lock() future, ok := heap.Pop(&queue).(*Future) + queueLock.Unlock() if !ok { log_error("there's shit on the work heap") continue @@ -70,3 +76,12 @@ func RunQueue() { future.work() } } + +func ResetQueue() { + queueLock.Lock() + defer queueLock.Unlock() + + log_info("Reseting worker queue.") + queue = make(Queue, 0, 32) + heap.Init(&queue) +}