server/player.go

183 lines
3.5 KiB
Go
Raw Normal View History

2013-08-19 20:43:26 -07:00
package main
import (
"encoding/json"
"errors"
"fmt"
2013-08-19 20:43:26 -07:00
"log"
"bitbucket.org/smcquay/bandwidth"
"code.google.com/p/go.net/websocket"
2013-08-19 20:43:26 -07:00
)
2014-02-16 23:59:17 -08:00
const maxMessageSize = 1024
type protoTalker struct {
ws *websocket.Conn
bw *bandwidth.Bandwidth
send chan Message
2014-02-17 01:07:29 -08:00
buff []byte
Id string
2013-08-19 20:43:26 -07:00
}
func NewProtoTalker(id string, ws *websocket.Conn, bw *bandwidth.Bandwidth) *protoTalker {
2014-02-17 01:07:29 -08:00
return &protoTalker{
send: make(chan Message, 16),
ws: ws,
bw: bw,
2014-02-17 01:07:29 -08:00
Id: id,
buff: make([]byte, maxMessageSize),
}
}
func (pt *protoTalker) sender() {
log.Printf("%s: client launched", pt.Id)
for things := range pt.send {
2014-02-16 23:59:17 -08:00
b, err := json.Marshal(things)
if err != nil {
break
}
n, err := pt.ws.Write(b)
pt.bw.AddTx <- n
2013-08-19 20:43:26 -07:00
if err != nil {
break
}
}
pt.ws.Close()
log.Printf("%s: spectator sender close", pt.Id)
}
func (pt *protoTalker) readJSON(buff []byte) (map[string]Instruction, error) {
msg := map[string]Instruction{}
n, err := pt.ws.Read(buff)
if err != nil {
log.Printf("%s: problem reading from player: %s", pt.Id, err)
return nil, err
}
pt.bw.AddRx <- n
if n == len(buff) {
errMsg := fmt.Sprintf("%s: read buffer overfull: %s", pt.Id, string(buff))
log.Printf(errMsg)
return msg, errors.New(errMsg)
}
err = json.Unmarshal(buff[:n], &msg)
if err != nil {
log.Printf("%s: problem reading from player: %s", pt.Id, err)
return nil, err
}
return msg, nil
}
type player struct {
Robots []*Robot
Instruction Instruction
protoTalker
2013-08-19 20:43:26 -07:00
}
func NewPlayer(id string, ws *websocket.Conn, bw *bandwidth.Bandwidth) *player {
2014-02-17 01:07:29 -08:00
return &player{
Robots: []*Robot{},
protoTalker: *NewProtoTalker(id, ws, bw),
2014-02-17 01:07:29 -08:00
}
}
2013-08-19 20:43:26 -07:00
func (p *player) recv() {
for {
2014-02-17 01:06:53 -08:00
msgs, err := p.readJSON(p.buff)
2014-02-16 23:59:17 -08:00
if err != nil {
log.Printf("%s: %s", p.Id, err)
2013-08-19 20:43:26 -07:00
break
}
2013-11-08 21:25:42 -08:00
for _, r := range p.Robots {
2013-11-06 22:50:59 -08:00
2013-11-08 22:26:56 -08:00
msg, ok := msgs[r.Id]
2013-11-08 21:25:42 -08:00
if !ok {
continue
2013-11-06 22:50:59 -08:00
}
2013-11-08 21:25:42 -08:00
if msg.Repair != nil && *msg.Repair == true {
r.ActiveScan = false
2013-11-08 21:25:42 -08:00
r.TargetSpeed = 0
r.FireAt = nil
r.MoveTo = nil
if r.RepairCounter <= 0 {
r.RepairCounter = 3.0
}
} else if msg.Scan != nil && *msg.Scan == true {
r.RepairCounter = 0
2013-11-08 21:25:42 -08:00
r.TargetSpeed = 0
r.FireAt = nil
r.MoveTo = nil
r.ActiveScan = true
2013-11-06 22:50:59 -08:00
} else {
2013-11-08 21:25:42 -08:00
r.RepairCounter = 0
r.ActiveScan = false
// Reapiring halts all other activity
if msg.MoveTo != nil {
r.MoveTo = msg.MoveTo
}
if msg.Heading != nil {
r.DesiredHeading = msg.Heading
}
2013-11-08 21:25:42 -08:00
if msg.FireAt != nil {
r.FireAt = msg.FireAt
2013-11-27 08:55:51 -08:00
} else {
r.FireAt = nil
2013-11-08 21:25:42 -08:00
}
if msg.TargetSpeed != nil {
r.TargetSpeed = float32(*msg.TargetSpeed)
} else {
r.TargetSpeed = r.Stats.Speed
}
}
2013-11-08 21:25:42 -08:00
if msg.Probe != nil {
r.Probe = msg.Probe
r.ProbeResult = nil
} else {
r.Probe = nil
2013-11-06 22:50:59 -08:00
}
2013-11-06 23:26:29 -08:00
2013-11-08 21:25:42 -08:00
if msg.Message != nil {
r.Message = *msg.Message
2013-11-06 23:26:29 -08:00
}
2013-08-19 20:43:26 -07:00
}
}
2013-11-08 21:25:42 -08:00
2014-01-23 21:09:27 -08:00
log.Printf("%s: recv close", p.Id)
2013-08-19 20:43:26 -07:00
p.ws.Close()
}
type Spectator struct {
protoTalker
}
func NewSpectator(id string, ws *websocket.Conn, bw *bandwidth.Bandwidth) *Spectator {
2014-02-17 01:07:29 -08:00
return &Spectator{
protoTalker: *NewProtoTalker(id, ws, bw),
2014-02-17 01:07:29 -08:00
}
}
func (s *Spectator) recv() {
for {
2014-02-17 01:06:53 -08:00
_, err := s.readJSON(s.buff)
if err != nil {
log.Printf("%s: %s", s.Id, err)
break
}
// After the first bit of handshaking, the rest of the messages should
// only be "{}" for spectators, and the following could hold true:
//
// if string(buff[:n]) != "{}" {
// log.Printf("protocol breach!!")
// break
// }
}
log.Printf("%s: recv close", s.Id)
s.ws.Close()
}