2013-08-19 20:43:26 -07:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2014-03-13 00:12:21 -07:00
|
|
|
"encoding/gob"
|
2014-02-04 08:00:15 -08:00
|
|
|
"encoding/json"
|
2013-08-19 20:43:26 -07:00
|
|
|
"log"
|
2014-03-03 21:57:39 -08:00
|
|
|
|
|
|
|
"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
|
|
|
|
|
2014-03-13 00:12:21 -07:00
|
|
|
type encoder interface {
|
|
|
|
Encode(v interface{}) error
|
|
|
|
}
|
|
|
|
|
|
|
|
type decoder interface {
|
|
|
|
Decode(v interface{}) error
|
|
|
|
}
|
|
|
|
|
|
|
|
type streamCounter struct {
|
|
|
|
ws *websocket.Conn
|
|
|
|
bw *bandwidth.Bandwidth
|
|
|
|
}
|
|
|
|
|
|
|
|
func (sc *streamCounter) Read(p []byte) (n int, err error) {
|
|
|
|
n, err = sc.ws.Read(p)
|
|
|
|
sc.bw.AddRx <- n
|
|
|
|
return n, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (sc *streamCounter) Write(p []byte) (n int, err error) {
|
|
|
|
n, err = sc.ws.Write(p)
|
|
|
|
sc.bw.AddTx <- n
|
|
|
|
return n, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (sc *streamCounter) Close() error {
|
|
|
|
return sc.ws.Close()
|
|
|
|
}
|
|
|
|
|
2014-02-17 00:42:52 -08:00
|
|
|
type protoTalker struct {
|
2014-03-13 00:12:21 -07:00
|
|
|
enc encoder
|
|
|
|
dec decoder
|
|
|
|
counter *streamCounter
|
|
|
|
send chan Message
|
|
|
|
Id string
|
2013-08-19 20:43:26 -07:00
|
|
|
}
|
|
|
|
|
2014-03-13 00:12:21 -07:00
|
|
|
func NewProtoTalker(id string, ws *websocket.Conn, bw *bandwidth.Bandwidth, encoding string) *protoTalker {
|
|
|
|
var enc encoder
|
|
|
|
var dec decoder
|
|
|
|
comptroller := &streamCounter{
|
|
|
|
ws: ws,
|
|
|
|
bw: bw,
|
|
|
|
}
|
|
|
|
if encoding == "json" {
|
|
|
|
enc = json.NewEncoder(comptroller)
|
|
|
|
dec = json.NewDecoder(comptroller)
|
|
|
|
} else {
|
|
|
|
enc = gob.NewEncoder(comptroller)
|
|
|
|
dec = gob.NewDecoder(comptroller)
|
|
|
|
}
|
2014-02-17 01:07:29 -08:00
|
|
|
return &protoTalker{
|
2014-03-13 00:12:21 -07:00
|
|
|
send: make(chan Message, 16),
|
|
|
|
enc: enc,
|
|
|
|
dec: dec,
|
|
|
|
counter: comptroller,
|
|
|
|
Id: id,
|
2014-02-17 01:07:29 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-17 00:42:52 -08:00
|
|
|
func (pt *protoTalker) sender() {
|
|
|
|
log.Printf("%s: client launched", pt.Id)
|
|
|
|
for things := range pt.send {
|
2014-03-13 00:12:21 -07:00
|
|
|
err := pt.enc.Encode(things)
|
2013-08-19 20:43:26 -07:00
|
|
|
if err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2014-03-13 00:12:21 -07:00
|
|
|
pt.counter.Close()
|
2014-02-17 00:42:52 -08:00
|
|
|
log.Printf("%s: spectator sender close", pt.Id)
|
|
|
|
}
|
|
|
|
|
|
|
|
type player struct {
|
|
|
|
Robots []*Robot
|
|
|
|
Instruction Instruction
|
|
|
|
protoTalker
|
2013-08-19 20:43:26 -07:00
|
|
|
}
|
|
|
|
|
2014-03-13 00:12:21 -07:00
|
|
|
func NewPlayer(id string, ws *websocket.Conn, bw *bandwidth.Bandwidth, encoding string) *player {
|
2014-02-17 01:07:29 -08:00
|
|
|
return &player{
|
|
|
|
Robots: []*Robot{},
|
2014-03-13 00:12:21 -07:00
|
|
|
protoTalker: *NewProtoTalker(id, ws, bw, encoding),
|
2014-02-17 01:07:29 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-19 20:43:26 -07:00
|
|
|
func (p *player) recv() {
|
|
|
|
for {
|
2014-03-13 00:12:21 -07:00
|
|
|
var msgs map[string]Instruction
|
|
|
|
err := p.dec.Decode(&msgs)
|
2014-02-16 23:59:17 -08:00
|
|
|
if err != nil {
|
2014-02-17 00:42:52 -08:00
|
|
|
log.Printf("%s: %s", p.Id, err)
|
2013-08-19 20:43:26 -07:00
|
|
|
break
|
|
|
|
}
|
2013-09-27 01:30:07 -07:00
|
|
|
|
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 {
|
2013-11-17 08:21:13 -08:00
|
|
|
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 {
|
2013-11-17 08:21:13 -08:00
|
|
|
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
|
|
|
|
}
|
2013-11-11 21:36:11 -08:00
|
|
|
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-27 20:33:57 -08:00
|
|
|
}
|
2013-11-08 21:25:42 -08:00
|
|
|
|
2013-11-27 20:33:57 -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)
|
2014-03-13 00:12:21 -07:00
|
|
|
p.counter.Close()
|
2013-08-19 20:43:26 -07:00
|
|
|
}
|
2014-02-17 00:42:52 -08:00
|
|
|
|
|
|
|
type Spectator struct {
|
|
|
|
protoTalker
|
|
|
|
}
|
|
|
|
|
2014-03-13 00:12:21 -07:00
|
|
|
func NewSpectator(id string, ws *websocket.Conn, bw *bandwidth.Bandwidth, encoding string) *Spectator {
|
2014-02-17 01:07:29 -08:00
|
|
|
return &Spectator{
|
2014-03-13 00:12:21 -07:00
|
|
|
protoTalker: *NewProtoTalker(id, ws, bw, encoding),
|
2014-02-17 01:07:29 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-17 00:42:52 -08:00
|
|
|
func (s *Spectator) recv() {
|
|
|
|
for {
|
2014-03-13 00:12:21 -07:00
|
|
|
var msgs interface{}
|
|
|
|
err := s.dec.Decode(&msgs)
|
2014-02-17 00:42:52 -08:00
|
|
|
if err != nil {
|
|
|
|
log.Printf("%s: %s", s.Id, err)
|
|
|
|
break
|
|
|
|
}
|
2014-03-13 00:12:21 -07:00
|
|
|
|
2014-02-17 00:42:52 -08:00
|
|
|
// 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)
|
2014-03-13 00:12:21 -07:00
|
|
|
s.counter.Close()
|
2014-02-17 00:42:52 -08:00
|
|
|
}
|