Stephen McQuay
6fd4138740
unfortunately there is an issue with how these are calculated, and they don't decrease as things quiet down. Well, the bad numbers are their for your consumption, and should Just Work TM when appropriate changes in bitbucket.org/smcquay/bandwith land. And they will. But I'm tired now.
183 lines
3.5 KiB
Go
183 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
|
|
"bitbucket.org/smcquay/bandwidth"
|
|
"code.google.com/p/go.net/websocket"
|
|
)
|
|
|
|
const maxMessageSize = 1024
|
|
|
|
type protoTalker struct {
|
|
ws *websocket.Conn
|
|
bw *bandwidth.Bandwidth
|
|
send chan Message
|
|
buff []byte
|
|
Id string
|
|
}
|
|
|
|
func NewProtoTalker(id string, ws *websocket.Conn, bw *bandwidth.Bandwidth) *protoTalker {
|
|
return &protoTalker{
|
|
send: make(chan Message, 16),
|
|
ws: ws,
|
|
bw: bw,
|
|
Id: id,
|
|
buff: make([]byte, maxMessageSize),
|
|
}
|
|
}
|
|
|
|
func (pt *protoTalker) sender() {
|
|
log.Printf("%s: client launched", pt.Id)
|
|
for things := range pt.send {
|
|
b, err := json.Marshal(things)
|
|
if err != nil {
|
|
break
|
|
}
|
|
n, err := pt.ws.Write(b)
|
|
pt.bw.AddTx <- n
|
|
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
|
|
}
|
|
|
|
func NewPlayer(id string, ws *websocket.Conn, bw *bandwidth.Bandwidth) *player {
|
|
return &player{
|
|
Robots: []*Robot{},
|
|
protoTalker: *NewProtoTalker(id, ws, bw),
|
|
}
|
|
}
|
|
|
|
func (p *player) recv() {
|
|
for {
|
|
msgs, err := p.readJSON(p.buff)
|
|
if err != nil {
|
|
log.Printf("%s: %s", p.Id, err)
|
|
break
|
|
}
|
|
|
|
for _, r := range p.Robots {
|
|
|
|
msg, ok := msgs[r.Id]
|
|
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
if msg.Repair != nil && *msg.Repair == true {
|
|
r.ActiveScan = false
|
|
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
|
|
r.TargetSpeed = 0
|
|
r.FireAt = nil
|
|
r.MoveTo = nil
|
|
r.ActiveScan = true
|
|
} else {
|
|
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
|
|
}
|
|
if msg.FireAt != nil {
|
|
r.FireAt = msg.FireAt
|
|
} else {
|
|
r.FireAt = nil
|
|
}
|
|
|
|
if msg.TargetSpeed != nil {
|
|
r.TargetSpeed = float32(*msg.TargetSpeed)
|
|
} else {
|
|
r.TargetSpeed = r.Stats.Speed
|
|
}
|
|
}
|
|
|
|
if msg.Probe != nil {
|
|
r.Probe = msg.Probe
|
|
r.ProbeResult = nil
|
|
} else {
|
|
r.Probe = nil
|
|
}
|
|
|
|
if msg.Message != nil {
|
|
r.Message = *msg.Message
|
|
}
|
|
}
|
|
}
|
|
|
|
log.Printf("%s: recv close", p.Id)
|
|
p.ws.Close()
|
|
}
|
|
|
|
type Spectator struct {
|
|
protoTalker
|
|
}
|
|
|
|
func NewSpectator(id string, ws *websocket.Conn, bw *bandwidth.Bandwidth) *Spectator {
|
|
return &Spectator{
|
|
protoTalker: *NewProtoTalker(id, ws, bw),
|
|
}
|
|
}
|
|
|
|
func (s *Spectator) recv() {
|
|
for {
|
|
_, 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()
|
|
}
|