From b32dfb835978861c497af3fa3deb27922c2daa27 Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Tue, 3 Nov 2020 23:42:42 +0000 Subject: [PATCH] fixing up entity ID clashes --- internal/sim/effect.go | 3 +-- internal/sim/player.go | 18 ++++++++++----- internal/sim/room.go | 34 --------------------------- internal/sim/server.go | 2 +- internal/sim/world.go | 52 +++++++++++++++++++++++++++++++++++++++++- 5 files changed, 65 insertions(+), 44 deletions(-) diff --git a/internal/sim/effect.go b/internal/sim/effect.go index 5bdbe74..d0997a5 100644 --- a/internal/sim/effect.go +++ b/internal/sim/effect.go @@ -3,8 +3,7 @@ package sim import "github.com/jordanorelli/astro-domu/internal/wire" type Effect interface { - //wire.Value - exec(*room, *player, int) result + exec(*world, *room, *player, int) result } type result struct { diff --git a/internal/sim/player.go b/internal/sim/player.go index 7dc2689..67bca2d 100644 --- a/internal/sim/player.go +++ b/internal/sim/player.go @@ -3,7 +3,6 @@ package sim import ( "encoding/json" "fmt" - "math/rand" "time" "github.com/gorilla/websocket" @@ -49,12 +48,17 @@ func (p *player) start(c chan Request, conn *websocket.Conn, r *room) { } welcome.Players[p.name] = wp } + p.Info("sending welcome to outbox") p.outbox <- wire.Response{Re: 1, Body: welcome} + p.Info("sent welcome, starting loops") go p.readLoop(c, conn) go p.runLoop(conn) } func (p *player) readLoop(c chan Request, conn *websocket.Conn) { + p.Info("readLoop started") + defer p.Info("readLoop ended") + for { _, b, err := conn.ReadMessage() if err != nil { @@ -69,10 +73,10 @@ func (p *player) readLoop(c chan Request, conn *websocket.Conn) { p.Error("unable to parse request: %v", err) continue } - // sn.Info("received message of type %T", req.Body) effect, ok := req.Body.(Effect) if !ok { + p.Error("request is not an effect, is %T", req.Body) continue } c <- Request{ @@ -81,10 +85,12 @@ func (p *player) readLoop(c chan Request, conn *websocket.Conn) { Wants: effect, } } - } func (p *player) runLoop(conn *websocket.Conn) { + p.Info("runLoop started") + defer p.Info("runLoop ended") + for { select { case res := <-p.outbox: @@ -133,12 +139,12 @@ func sendResponse(conn *websocket.Conn, res wire.Response) error { type spawnPlayer struct{} -func (s spawnPlayer) exec(r *room, p *player, seq int) result { +func (s spawnPlayer) exec(w *world, r *room, p *player, seq int) result { for n, t := range r.tiles { if t.here == nil { x, y := n%r.Width, n/r.Width e := entity{ - ID: rand.Intn(9000), + ID: <-w.nextID, Position: math.Vec{x, y}, Glyph: '@', behavior: doNothing{}, @@ -155,7 +161,7 @@ type Move math.Vec func (Move) NetTag() string { return "move" } -func (m *Move) exec(r *room, p *player, seq int) result { +func (m *Move) exec(w *world, r *room, p *player, seq int) result { pos := p.avatar.Position target := pos.Add(math.Vec(*m)) p.Info("running move for player %s from %v to %v", p.name, *m, target) diff --git a/internal/sim/room.go b/internal/sim/room.go index a0d4adb..7bfeda6 100644 --- a/internal/sim/room.go +++ b/internal/sim/room.go @@ -1,8 +1,6 @@ package sim import ( - "time" - "github.com/jordanorelli/astro-domu/internal/math" "github.com/jordanorelli/astro-domu/internal/wire" "github.com/jordanorelli/blammo" @@ -16,38 +14,6 @@ type room struct { players map[string]*player } -func (r *room) update(dt time.Duration) { - for _, p := range r.players { - if p.pending == nil { - continue - } - req := p.pending - p.pending = nil - - res := req.Wants.exec(r, p, req.Seq) - if res.reply != nil { - p.outbox <- wire.Response{Re: req.Seq, Body: res.reply} - } else { - p.outbox <- wire.Response{Re: req.Seq, Body: wire.OK{}} - } - } - - for _, t := range r.tiles { - if t.here != nil { - t.here.update(dt) - } - } - - frame := wire.Frame{ - Entities: r.allEntities(), - Players: r.playerAvatars(), - } - - for _, p := range r.players { - p.outbox <- wire.Response{Body: frame} - } -} - func (r *room) allEntities() map[int]wire.Entity { all := make(map[int]wire.Entity, 4) for _, t := range r.tiles { diff --git a/internal/sim/server.go b/internal/sim/server.go index 5b992c2..089feb9 100644 --- a/internal/sim/server.go +++ b/internal/sim/server.go @@ -27,7 +27,7 @@ func (s *Server) Start(host string, port int) error { } s.world = newWorld(s.Log.Child("world")) - go s.world.run(30) + go s.world.run(2) addr := fmt.Sprintf("%s:%d", host, port) lis, err := net.Listen("tcp", addr) diff --git a/internal/sim/world.go b/internal/sim/world.go index 29290b2..52dd56d 100644 --- a/internal/sim/world.go +++ b/internal/sim/world.go @@ -15,6 +15,7 @@ type world struct { *blammo.Log inbox chan Request connect chan connect + nextID chan int done chan bool lastEntityID int @@ -51,12 +52,25 @@ func newWorld(log *blammo.Log) *world { inbox: make(chan Request), connect: make(chan connect), players: make(map[string]*player), + nextID: make(chan int), } } func (w *world) run(hz int) { defer w.Info("simulation has exited run loop") + go func() { + lastID := 1 + for { + select { + case <-w.done: + return + case w.nextID <- lastID: + lastID++ + } + } + }() + period := time.Second / time.Duration(hz) w.Info("starting world with a tick rate of %dhz, frame duration of %v", hz, period) ticker := time.NewTicker(period) @@ -66,9 +80,12 @@ func (w *world) run(hz int) { select { case c := <-w.connect: w.register(c) + w.Info("finished registration for: %v", c) case req := <-w.inbox: + w.Info("read request off of inbox: %v", req) w.handleRequest(req) + w.Info("finished handling request: %v", req) case <-ticker.C: w.tick(time.Since(lastTick)) @@ -123,6 +140,7 @@ func (w *world) register(c connect) { foyer.players[c.login.Name] = &p w.players[c.login.Name] = &p + w.Info("starting player...") p.start(w.inbox, c.conn, foyer) } @@ -134,7 +152,39 @@ func (w *world) stop() error { } func (w *world) tick(d time.Duration) { + // run all player effects + for _, r := range w.rooms { + for _, p := range r.players { + if p.pending == nil { + continue + } + req := p.pending + p.pending = nil + + res := req.Wants.exec(w, r, p, req.Seq) + if res.reply != nil { + p.outbox <- wire.Response{Re: req.Seq, Body: res.reply} + } else { + p.outbox <- wire.Response{Re: req.Seq, Body: wire.OK{}} + } + } + } + + // run all object effects for _, r := range w.rooms { - r.update(d) + for _, t := range r.tiles { + if t.here != nil { + t.here.update(d) + } + } + + frame := wire.Frame{ + Entities: r.allEntities(), + Players: r.playerAvatars(), + } + + for _, p := range r.players { + p.outbox <- wire.Response{Body: frame} + } } }