From 55d638c7f02a8fd9efd73bee358eb4a980c5382c Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Wed, 28 Oct 2020 18:25:25 +0000 Subject: [PATCH] player spawninnnnnng into a room now --- internal/server/server.go | 1 - internal/server/session.go | 6 ++-- internal/sim/effect.go | 7 ++++- internal/sim/player.go | 43 ++++++++++++++++++++++++++-- internal/sim/request.go | 1 + internal/sim/room.go | 34 +++++++++++++++++++---- internal/sim/world.go | 57 +++++++++++++++----------------------- internal/ui/ui.go | 1 - 8 files changed, 102 insertions(+), 48 deletions(-) diff --git a/internal/server/server.go b/internal/server/server.go index 9b05777..e28f8eb 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -108,7 +108,6 @@ func (s *Server) dropSession(sn *session) { close(sn.done) delete(s.sessions, sn.id) - s.world.DespawnPlayer(sn.entityID) s.waitOnSessions.Add(-1) s.Info("dropped session %d after %v time connected, %d sessions active", sn.id, time.Since(sn.start), len(s.sessions)) diff --git a/internal/server/session.go b/internal/server/session.go index a3cfb91..9234529 100644 --- a/internal/server/session.go +++ b/internal/server/session.go @@ -96,17 +96,17 @@ func (sn *session) read() { sn.Name = v.Name sn.world.Inbox <- sim.Request{ From: sn.Name, - Wants: sim.SpawnPlayer{ + Seq: req.Seq, + Wants: &sim.SpawnPlayer{ Outbox: sn.outbox, }, } - sn.outbox <- wire.Response{req.Seq, wire.OK{}} case sim.Effect: sn.world.Inbox <- sim.Request{ From: sn.Name, + Seq: req.Seq, Wants: v, } - sn.outbox <- wire.Response{req.Seq, wire.OK{}} default: sn.outbox <- wire.ErrorResponse(req.Seq, "not sure how to handle that") } diff --git a/internal/sim/effect.go b/internal/sim/effect.go index 15f9d8a..fd4e5f8 100644 --- a/internal/sim/effect.go +++ b/internal/sim/effect.go @@ -4,5 +4,10 @@ import "github.com/jordanorelli/astro-domu/internal/wire" type Effect interface { wire.Value - exec(*World, string) + exec(*room, string, int) result +} + +type result struct { + reply wire.Value + announce wire.Value } diff --git a/internal/sim/player.go b/internal/sim/player.go index aaa0ffb..dace622 100644 --- a/internal/sim/player.go +++ b/internal/sim/player.go @@ -10,8 +10,10 @@ import ( // player represents a player character in the simulation type player struct { *blammo.Log - sessionID int + *room + name string outbox chan wire.Response + sessionID int entityID int pending []Request } @@ -24,13 +26,41 @@ type Move [2]int func (Move) NetTag() string { return "move" } +func (m *Move) exec(r *room, from *player, seq int) { + +} + // SpawnPlayer is a request to spawn a player type SpawnPlayer struct { Outbox chan wire.Response + queued bool } -func (s SpawnPlayer) exec(w *World, from string) { - w.Info("spawn player requested for: %s", from) +func (s *SpawnPlayer) exec(r *room, from string, seq int) result { + if !s.queued { + r.Info("spawn player requested for: %s", from) + + if _, ok := r.players[from]; ok { + s.Outbox <- wire.ErrorResponse(seq, "a player is already logged in as %q", from) + return result{} + } + + p := &player{ + Log: r.Log.Child("players").Child(from), + room: r, + name: from, + outbox: s.Outbox, + pending: make([]Request, 0, 32), + } + p.pending = append(p.pending, Request{Seq: seq, From: from, Wants: s}) + r.players[from] = p + s.queued = true + return result{} + } + + return result{ + reply: Welcome{Room: r.name}, + } } func (SpawnPlayer) NetTag() string { return "player/spawn" } @@ -40,6 +70,13 @@ type PlayerSpawned struct { Name string } +type Welcome struct { + Room string `json:"room"` +} + +func (Welcome) NetTag() string { return "player/welcome" } + func init() { wire.Register(func() wire.Value { return new(Move) }) + wire.Register(func() wire.Value { return new(Welcome) }) } diff --git a/internal/sim/request.go b/internal/sim/request.go index 2853dd6..d41e434 100644 --- a/internal/sim/request.go +++ b/internal/sim/request.go @@ -2,5 +2,6 @@ package sim type Request struct { From string + Seq int Wants Effect } diff --git a/internal/sim/room.go b/internal/sim/room.go index a13a28f..9f89a55 100644 --- a/internal/sim/room.go +++ b/internal/sim/room.go @@ -3,22 +3,46 @@ package sim import ( "time" + "github.com/jordanorelli/astro-domu/internal/wire" "github.com/jordanorelli/blammo" ) type room struct { *blammo.Log - name string - origin point - width int - height int - tiles []tile + name string + origin point + width int + height int + tiles []tile + players map[string]*player } func (r *room) update(dt time.Duration) { + // announcements := make([]result, 0, 8) + + for _, p := range r.players { + for _, req := range p.pending { + res := req.Wants.exec(r, p.name, req.Seq) + p.outbox <- wire.Response{Re: req.Seq, Body: res.reply} + } + p.pending = p.pending[0:0] + } + for _, t := range r.tiles { for _, e := range t.contents { e.update(dt) } } } + +func (r *room) addPlayer(p *player) { + r.players[p.name] = p +} + +func (r *room) removePlayer(name string) bool { + if _, ok := r.players[name]; ok { + delete(r.players, name) + return true + } + return false +} diff --git a/internal/sim/world.go b/internal/sim/world.go index 358d118..6657456 100644 --- a/internal/sim/world.go +++ b/internal/sim/world.go @@ -3,6 +3,7 @@ package sim import ( "time" + "github.com/jordanorelli/astro-domu/internal/wire" "github.com/jordanorelli/blammo" ) @@ -19,12 +20,13 @@ type World struct { func NewWorld(log *blammo.Log) *World { foyer := room{ - Log: log.Child("foyer"), - name: "foyer", - origin: point{0, 0}, - width: 10, - height: 10, - tiles: make([]tile, 100), + Log: log.Child("foyer"), + name: "foyer", + origin: point{0, 0}, + width: 10, + height: 10, + tiles: make([]tile, 100), + players: make(map[string]*player), } return &World{ Log: log, @@ -47,14 +49,27 @@ func (w *World) Run(hz int) { select { case req := <-w.Inbox: w.Info("read from inbox: %v", req) + if req.From == "" { - req.Wants.exec(w, "") + w.Error("request has no from: %v", req) break } + + if spawn, ok := req.Wants.(*SpawnPlayer); ok { + if _, ok := w.players[req.From]; ok { + spawn.Outbox <- wire.ErrorResponse(req.Seq, "a player is already logged in as %q", req.From) + break + } + spawn.exec(&w.rooms[0], req.From, req.Seq) + break + } + p, ok := w.players[req.From] if !ok { - break + w.Error("received non login request of type %T from unknown player %q", req.Wants, req.From) } + break + p.pending = append(p.pending, req) case <-ticker.C: @@ -73,32 +88,6 @@ func (w *World) Stop() error { return nil } -// func (w *World) SpawnPlayer(id int) int { -// w.lastEntityID++ -// r := w.rooms[0] -// w.Info("spawning player with id: %d into room %q", id, r.name) -// t := &r.tiles[0] -// p := player{ -// Log: w.Child("players").Child(strconv.Itoa(id)), -// entityID: w.lastEntityID, -// } -// t.addEntity(&p) -// return p.entityID -// } - -func (w *World) DespawnPlayer(id int) { - w.Info("despawning player with id: %d", id) - for _, r := range w.rooms { - for _, t := range r.tiles { - if e := t.removeEntity(id); e != nil { - w.Info("player removed from room %q", r.name) - return - } - } - } - w.Error("player was not found in any room") -} - func (w *World) tick(d time.Duration) { for _, r := range w.rooms { r.update(d) diff --git a/internal/ui/ui.go b/internal/ui/ui.go index 8505e9a..d2895b1 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -118,7 +118,6 @@ func (ui *UI) handleUserInput() bool { // someone else shut us down, so return false return false } - ui.Info("screen sees event: %v", e) switch v := e.(type) { case *tcell.EventKey: