diff --git a/game.go b/game.go index 346b4f9..deee642 100644 --- a/game.go +++ b/game.go @@ -9,13 +9,6 @@ import ( const maxPlayer = 128 -type Config struct { - ID string `json:"id"` - Name string `json:"name"` - // TODO: candidate for embedding? - Stats Stats `json:"stats"` -} - type Boardstate struct { Robots []Robot `json:"robots"` Projectiles []Projectile `json:"projectiles"` diff --git a/http.go b/http.go index 3a43e5b..18d16f1 100644 --- a/http.go +++ b/http.go @@ -1,10 +1,8 @@ package main import ( - "code.google.com/p/go.net/websocket" "encoding/json" "fmt" - "log" "net/http" "strings" ) @@ -77,62 +75,3 @@ func listGames(w http.ResponseWriter, req *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) } } - -func addPlayer(ws *websocket.Conn) { - // route to appropriate game ... - var gid GameID - err := websocket.JSON.Receive(ws, &gid) - if err != nil { - log.Println("problem parsing the requested game id") - return - } - - games.Lock() - game, ok := games.m[gid.Id] - games.Unlock() - - if !ok { - log.Println("ERROR: game not found") - websocket.JSON.Send(ws, NewFailure("game 404")) - return - } - - id := idg.Hash() - - conf, err := Negociate(ws, id, game.width, game.height) - if err != nil { - websocket.JSON.Send(ws, NewFailure(err.Error())) - } - - if conf != nil { - p := &player{ - Robot: Robot{ - Stats: conf.Stats, - Id: id, - Name: conf.Name, - Health: conf.Stats.Hp, - Scanners: make([]Scanner, 0)}, - send: make(chan *Boardstate), - ws: ws, - } - p.reset() - game.register <- p - defer func() { - game.unregister <- p - }() - go p.sender() - p.recv() - log.Printf("game %s: player %v has been disconnected from this game\n", gid.Id, p.Robot.Id) - } else { - s := &Spectator{ - send: make(chan *Boardstate), - ws: ws, - } - game.sregister <- s - defer func() { - game.sunregister <- s - }() - s.sender() - log.Printf("game %s: spectator %+v has been disconnected from this game\n", s) - } -} diff --git a/protocol.go b/protocol.go index 4d78ad7..139deb7 100644 --- a/protocol.go +++ b/protocol.go @@ -2,25 +2,25 @@ package main import ( "code.google.com/p/go.net/websocket" - "errors" "log" ) +// < the name of the game we want to join type GameID struct { Id string `json:"id"` } // > identify -type IdRequest struct { - Type string `json:"type"` - AssignedID string `json:"id"` +type PlayerID struct { + Type string `json:"type"` + Hash string `json:"id"` Failure } -func NewIdRequest(id string) *IdRequest { - return &IdRequest{ - Type: "idreq", - AssignedID: id, +func NewPlayerID(id string) *PlayerID { + return &PlayerID{ + Type: "idreq", + Hash: id, } } @@ -39,6 +39,11 @@ func (c *ClientID) Valid() (bool, string) { return false, "usergent must be 'robot' or 'spectator'" } +type ClientConfig struct { + ID string `json:"id"` + Stats Stats `json:"stats"` +} + type BoardSize struct { Width float64 `json:"width"` Height float64 `json:"height"` @@ -86,18 +91,39 @@ func NewFailure(reason string) *Failure { } } -func Negociate(ws *websocket.Conn, id string, width, height float64) (*Config, error) { - var err error - - err = websocket.JSON.Send(ws, NewIdRequest(id)) +func addPlayer(ws *websocket.Conn) { + // route to appropriate game ... + var gid GameID + err := websocket.JSON.Receive(ws, &gid) if err != nil { - return nil, errors.New("generic server error") + log.Println("problem parsing the requested game id") + return + } + + games.Lock() + game, ok := games.m[gid.Id] + games.Unlock() + + if !ok { + log.Printf("ERROR: game %s not found", gid.Id) + websocket.JSON.Send(ws, NewFailure("game 404")) + return + } + + player_id := idg.Hash() + err = websocket.JSON.Send(ws, NewPlayerID(player_id)) + if err != nil { + log.Printf("game %s: unable to send player_id to player %s", gid.Id, player_id) + websocket.JSON.Send(ws, NewFailure("send error")) + return } var clientid ClientID err = websocket.JSON.Receive(ws, &clientid) if err != nil { - return nil, errors.New("could not parse id") + log.Printf("unable to parse ClientID: gid: %s, player: %s", gid.Id, player_id) + websocket.JSON.Send(ws, NewFailure("parse error")) + return } if v, msg := clientid.Valid(); !v { log.Printf("clientid is invalid: %+v", clientid) @@ -105,40 +131,69 @@ func Negociate(ws *websocket.Conn, id string, width, height float64) (*Config, e ws, NewFailure(msg), ) - return nil, errors.New(msg) + return } - log.Printf("clientid: %+v", clientid) + log.Printf("%s: %s clientid: %+v", gid.Id, player_id, clientid) - gameParam := NewGameParam(width, height) + gameParam := NewGameParam(game.width, game.height) err = websocket.JSON.Send(ws, gameParam) if err != nil { - websocket.JSON.Send(ws, NewFailure("generic server error")) - return nil, err + log.Printf("%s %s game param parse error", gid.Id, player_id) + websocket.JSON.Send(ws, NewFailure("game param parse error")) + return } log.Printf("gameparam: %+v", gameParam) + switch clientid.Type { case "robot": - var conf Config - log.Printf("got here?") + var conf ClientConfig for { - log.Printf("%s Waiting for client to send conf ...", id) + log.Printf("%s Waiting for client to send conf ...", player_id) err = websocket.JSON.Receive(ws, &conf) log.Printf("conf received: %+v", conf) if err != nil { - return nil, err + log.Printf("%s %s config parse error", gid.Id, player_id) + websocket.JSON.Send(ws, NewFailure("config parse error")) + return } // TODO: verify conf's type if conf.Stats.Valid() { - _ = websocket.JSON.Send(ws, NewHandshake(id, true)) + _ = websocket.JSON.Send(ws, NewHandshake(player_id, true)) break } else { - _ = websocket.JSON.Send(ws, NewHandshake(id, false)) + _ = websocket.JSON.Send(ws, NewHandshake(player_id, false)) } } - conf.Name = clientid.Name - return &conf, nil + + p := &player{ + Robot: Robot{ + Stats: conf.Stats, + Id: player_id, + Name: clientid.Name, + Health: conf.Stats.Hp, + Scanners: make([]Scanner, 0)}, + send: make(chan *Boardstate), + ws: ws, + } + p.reset() + game.register <- p + defer func() { + game.unregister <- p + }() + go p.sender() + p.recv() + log.Printf("game %s: player %v has been disconnected from this game\n", gid.Id, p.Robot.Id) case "spectator": - return nil, nil + //return nil, nil + s := &Spectator{ + send: make(chan *Boardstate), + ws: ws, + } + game.sregister <- s + defer func() { + game.sunregister <- s + }() + s.sender() + log.Printf("game %s: spectator %+v has been disconnected from this game\n", s) } - return nil, nil }