From ca4015a4d42ee6220585d9bc525d701e769b45c8 Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Mon, 3 Feb 2020 02:32:24 +0000 Subject: [PATCH] broadcasting death notifications --- server/main.go | 1 + server/message.go | 2 +- server/player.go | 28 ++++++++++++++++++++++------ server/request.go | 32 ++++++++++++++++++++++++++++---- server/server.go | 4 ++++ server/soul.go | 6 ++++++ 6 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 server/soul.go diff --git a/server/main.go b/server/main.go index 55c532c..d40df89 100644 --- a/server/main.go +++ b/server/main.go @@ -17,6 +17,7 @@ func main() { Log: log, join: make(chan player), inbox: make(chan message), + souls: make(map[string]soul), } s.init() go s.run() diff --git a/server/message.go b/server/message.go index bc4f32f..42e25c9 100644 --- a/server/message.go +++ b/server/message.go @@ -1,6 +1,6 @@ package main type message struct { - from int + from *player text string } diff --git a/server/player.go b/server/player.go index b34f12e..012f8bf 100644 --- a/server/player.go +++ b/server/player.go @@ -12,9 +12,11 @@ import ( type player struct { *blammo.Log - conn *websocket.Conn - server *server - id int + conn *websocket.Conn + server *server + id int + username string + outbox chan string } func (p *player) run() { @@ -24,6 +26,7 @@ func (p *player) run() { ctx, cancel := context.WithCancel(context.Background()) go p.writeMessages(ctx) p.readMessages(cancel) + p.outbox = nil p.conn.Close() } @@ -52,7 +55,7 @@ func (p *player) readMessages(cancel func()) { p.Child("rcv").Info(string(b)) } p.server.inbox <- message{ - from: p.id, + from: p, text: string(b), } } @@ -76,12 +79,25 @@ func (p *player) writeMessages(ctx context.Context) { return } - fmt.Fprintf(w, "%d tick: %v", n, t) + fmt.Fprintf(w, "tick %d: %v", n, t) if err := w.Close(); err != nil { p.Error("close frame error: %v", err) return } - p.Info("wrote a tick") + case msg := <-p.outbox: + p.Info("writing message from outbox: %s", msg) + w, err := p.conn.NextWriter(websocket.TextMessage) + if err != nil { + p.Error("error getting writer: %v", err) + return + } + + w.Write([]byte(msg)) + if err := w.Close(); err != nil { + p.Error("close frame error: %v", err) + return + } + case <-ctx.Done(): return } diff --git a/server/request.go b/server/request.go index 5269ed7..c78c7e1 100644 --- a/server/request.go +++ b/server/request.go @@ -2,6 +2,7 @@ package main import ( "encoding/json" + "fmt" ) type request struct { @@ -31,7 +32,7 @@ type vector3 struct { } type command interface { - exec(*server) + exec(*server, *player) } type collectSoul struct { @@ -39,7 +40,7 @@ type collectSoul struct { Position vector3 `json:"position"` } -func (c *collectSoul) exec(s *server) { +func (c *collectSoul) exec(s *server, from *player) { } type login struct { @@ -47,12 +48,35 @@ type login struct { Password string `json:"password"` } -func (l *login) exec(s *server) { +func (l *login) exec(s *server, from *player) { + from.username = l.Username } type death struct { Position vector3 `json:"position"` } -func (d *death) exec(s *server) { +func (d *death) exec(s *server, from *player) { + s.Info("executing a death: %#v", d) + _soul := soul{ + PlayerName: from.username, + Position: d.Position, + } + s.souls[from.username] = _soul + + b, err := json.Marshal(_soul) + if err != nil { + s.Error("unable to serialize soul: %v", err) + return + } + + msg := fmt.Sprintf("spawn-soul %s", string(b)) + + for _, player := range s.players { + select { + case player.outbox <- msg: + default: + s.Error("can't write to player %s's outbox", player.username) + } + } } diff --git a/server/server.go b/server/server.go index dc97254..609adc0 100644 --- a/server/server.go +++ b/server/server.go @@ -16,6 +16,7 @@ type server struct { players map[int]*player join chan player inbox chan message + souls map[string]soul } func (s *server) init() { @@ -42,6 +43,7 @@ func (s *server) play(w http.ResponseWriter, r *http.Request) { s.join <- player{ conn: conn, server: s, + outbox: make(chan string, 8), } } @@ -60,6 +62,7 @@ func (s *server) step(pc int) { p.id = pc p.Log = s.Child("players").Child(strconv.Itoa(p.id)) go p.run() + s.players[p.id] = &p case m := <-s.inbox: s.Info("received message: %v", m) var req request @@ -69,5 +72,6 @@ func (s *server) step(pc int) { } cmd := req.parse(m.text) s.Info("cmd: %#v", cmd) + cmd.exec(s, m.from) } } diff --git a/server/soul.go b/server/soul.go new file mode 100644 index 0000000..3b84e6e --- /dev/null +++ b/server/soul.go @@ -0,0 +1,6 @@ +package main + +type soul struct { + PlayerName string `json:"playerName"` + Position vector3 `json:"position"` +}