diff --git a/commands.go b/commands.go index 40fdade..693d4e6 100644 --- a/commands.go +++ b/commands.go @@ -159,13 +159,43 @@ func move(conn *Connection, to *System) { }) } -// var bombCommand = &Command{ -// name: "bomb", -// help: "bombs a system, with a big space bomb", -// handler: func(conn *Connection, args ...string) { -// -// }, -// } +var bombCommand = &Command{ + name: "bomb", + help: "bombs a system, with a big space bomb", + handler: func(conn *Connection, args ...string) { + dest_name := strings.Join(args, " ") + to, ok := nameIndex[dest_name] + if ok { + bomb(conn, to) + return + } + + id_n, err := strconv.Atoi(dest_name) + if err != nil { + fmt.Fprintf(conn, `hmm, I don't know a system by the name "%s", try something else\n`, dest_name) + return + } + + to, ok = index[id_n] + if !ok { + fmt.Fprintf(conn, `oh dear, there doesn't seem to be a system with id %d\n`, id_n) + return + } + if !conn.CanBomb() { + fmt.Fprintf(conn, "weapons are still reloading. Can bomb again in %v\n", conn.NextBomb()) + return + } + bomb(conn, to) + }, +} + +func bomb(conn *Connection, to *System) { + delay := conn.System().TimeTo(to) + delay = time.Duration(int64(float64(delay/time.Nanosecond) * 1.1)) + After(delay, func() { + to.Bombed(conn) + }) +} func isCommand(name string) bool { _, ok := commandRegistry[name] @@ -179,6 +209,11 @@ func runCommand(conn *Connection, name string, args ...string) { return } + if conn.dead { + fmt.Fprintf(conn, "you're dead.\n") + return + } + if conn.InTransit() && !cmd.mobile { fmt.Fprintf(conn, "command %s can not be used while in transit", name) return @@ -192,12 +227,12 @@ func registerCommand(c *Command) { func init() { commandRegistry = make(map[string]*Command, 16) + registerCommand(bombCommand) + registerCommand(broadcastCommand) registerCommand(commandsCommand) + registerCommand(gotoCommand) registerCommand(helpCommand) registerCommand(infoCommand) registerCommand(nearbyCommand) registerCommand(scanCommand) - registerCommand(gotoCommand) - registerCommand(broadcastCommand) - // registerCommand(bombCommand) } diff --git a/session.go b/session.go index b12e919..775679b 100644 --- a/session.go +++ b/session.go @@ -8,19 +8,26 @@ import ( "time" ) +var connected = make(map[*Connection]bool, 32) + type Connection struct { net.Conn *bufio.Reader player *Player location *System lastScan time.Time + lastBomb time.Time + kills int + dead bool } func NewConnection(conn net.Conn) *Connection { - return &Connection{ + c := &Connection{ Conn: conn, Reader: bufio.NewReader(conn), } + connected[c] = true + return c } func (c *Connection) Login() { @@ -65,6 +72,7 @@ func (c *Connection) System() *System { func (c *Connection) Close() error { log_info("player disconnecting: %s", c.PlayerName()) + delete(connected, c) return c.Conn.Close() } @@ -83,10 +91,65 @@ func (c *Connection) RecordScan() { c.lastScan = time.Now() } +func (c *Connection) RecordBomb() { + c.lastBomb = time.Now() +} + func (c *Connection) CanScan() bool { return time.Since(c.lastScan) > 1*time.Minute } +func (c *Connection) CanBomb() bool { + return time.Since(c.lastBomb) > 1500*time.Millisecond +} + func (c *Connection) NextScan() time.Duration { return -time.Since(c.lastScan.Add(time.Minute)) } + +func (c *Connection) NextBomb() time.Duration { + return -time.Since(c.lastBomb.Add(1500 * time.Millisecond)) +} + +func (c *Connection) MadeKill(victim *Connection) { + c.kills += 1 + if c.kills == 3 { + c.Win() + } +} + +func (c *Connection) Win() { + for conn, _ := range connected { + fmt.Fprintf(conn, "player %s has won.\n", c.PlayerName()) + conn.Close() + } +} + +func (c *Connection) Die() { + fmt.Fprintf(c, "you were bombed. You will respawn in 2 minutes.\n") + c.dead = true + c.System().Leave(c) + After(30*time.Second, func() { + fmt.Fprintf(c, "respawn in 90 seconds.\n") + }) + After(time.Minute, func() { + fmt.Fprintf(c, "respawn in 60 seconds.\n") + }) + After(90*time.Second, func() { + fmt.Fprintf(c, "respawn in 30 seconds.\n") + }) + After(2*time.Minute, c.Respawn) +} + +func (c *Connection) Respawn() { + c.dead = false + +WUT: + s, err := randomSystem() + if err != nil { + log_error("error in respawn: %v", err) + goto WUT + } + s.Arrive(c) + +} diff --git a/system.go b/system.go index 27c00dd..a3f3aec 100644 --- a/system.go +++ b/system.go @@ -72,6 +72,32 @@ func (s *System) TimeTo(other *System) time.Duration { return time.Duration(int64(s.DistanceTo(other) * 100000000)) } +func (s *System) Bombed(bomber *Connection) { + s.EachConn(func(conn *Connection) { + conn.Die() + bomber.MadeKill(conn) + }) + + for id, _ := range index { + if id == s.id { + continue + } + delay := s.TimeTo(index[id]) + id2 := id + After(delay, func() { + bombNotice(id2, s.id) + }) + } +} + +func bombNotice(to_id, from_id int) { + to := index[to_id] + from := index[from_id] + to.EachConn(func(conn *Connection) { + fmt.Fprintf(conn, "a bombing has been observed on %s\n", from.name) + }) +} + func (e System) String() string { return fmt.Sprintf("", e.name, e.x, e.y, e.z, e.planets) }