diff --git a/internal/sim/log.go b/internal/sim/log.go new file mode 100644 index 0000000..1922e6e --- /dev/null +++ b/internal/sim/log.go @@ -0,0 +1,20 @@ +package sim + +import ( + "os" + + "github.com/jordanorelli/blammo" +) + +func defaultLog() *blammo.Log { + stdout := blammo.NewLineWriter(os.Stdout) + stderr := blammo.NewLineWriter(os.Stderr) + + options := []blammo.Option{ + blammo.DebugWriter(stdout), + blammo.InfoWriter(stdout), + blammo.ErrorWriter(stderr), + } + + return blammo.NewLog("sim", options...) +} diff --git a/internal/sim/player.go b/internal/sim/player.go index b502f6d..ac056a0 100644 --- a/internal/sim/player.go +++ b/internal/sim/player.go @@ -6,7 +6,6 @@ import ( "github.com/jordanorelli/blammo" ) -// player is a player session in the simulation, eek type player struct { *blammo.Log *room diff --git a/internal/sim/server.go b/internal/sim/server.go index 5da565b..af1f66c 100644 --- a/internal/sim/server.go +++ b/internal/sim/server.go @@ -5,7 +5,6 @@ import ( "fmt" "net" "net/http" - "os" "strconv" "sync" "time" @@ -19,7 +18,7 @@ import ( type Server struct { *blammo.Log http *http.Server - world *World + world *world sync.Mutex lastSessionID int @@ -29,20 +28,11 @@ type Server struct { func (s *Server) Start(host string, port int) error { if s.Log == nil { - stdout := blammo.NewLineWriter(os.Stdout) - stderr := blammo.NewLineWriter(os.Stderr) - - options := []blammo.Option{ - blammo.DebugWriter(stdout), - blammo.InfoWriter(stdout), - blammo.ErrorWriter(stderr), - } - - s.Log = blammo.NewLog("astro", options...).Child("server") + s.Log = defaultLog().Child("server") } - s.world = NewWorld(s.Log.Child("world")) - go s.world.Run(3) + s.world = newWorld(s.Log.Child("world")) + go s.world.run(3) addr := fmt.Sprintf("%s:%d", host, port) lis, err := net.Listen("tcp", addr) @@ -131,7 +121,7 @@ func (s *Server) Shutdown() { go func() { defer wg.Done() - if err := s.world.Stop(); err != nil { + if err := s.world.stop(); err != nil { s.Error("error stopping the simulation: %v", err) } }() diff --git a/internal/sim/session.go b/internal/sim/session.go index cb840d6..0d8f941 100644 --- a/internal/sim/session.go +++ b/internal/sim/session.go @@ -84,7 +84,7 @@ func (sn *session) read(c chan Request) { var req wire.Request if err := json.Unmarshal(b, &req); err != nil { sn.Error("unable to parse request: %v", err) - sn.outbox <- wire.ErrorResponse(req.Seq, "unable to parse request: %v", err) + sn.enqueue(wire.ErrorResponse(req.Seq, "unable to parse request: %v", err)) break } sn.Info("received message of type %T", req.Body) @@ -107,10 +107,10 @@ func (sn *session) read(c chan Request) { Wants: v, } default: - sn.outbox <- wire.ErrorResponse(req.Seq, "not sure how to handle that") + sn.enqueue(wire.ErrorResponse(req.Seq, "not sure how to handle that")) } case websocket.BinaryMessage: - sn.outbox <- wire.ErrorResponse(0, "unable to parse binary frames") + sn.enqueue(wire.ErrorResponse(0, "unable to parse binary frames")) } } } @@ -139,3 +139,16 @@ func (sn *session) sendResponse(res wire.Response) error { sn.Child("sent-frame").Info(string(payload)) return nil } + +func (sn *session) enqueue(res wire.Response) { + select { + case sn.outbox <- res: + return + default: + select { + case <-sn.outbox: + sn.enqueue(res) + default: + } + } +} diff --git a/internal/sim/world.go b/internal/sim/world.go index 9ca5c47..2324c5d 100644 --- a/internal/sim/world.go +++ b/internal/sim/world.go @@ -8,8 +8,8 @@ import ( "github.com/jordanorelli/blammo" ) -// World is the entire simulated world. A world consists of many rooms. -type World struct { +// world is the entire simulated world. A world consists of many rooms. +type world struct { *blammo.Log Inbox chan Request @@ -19,7 +19,7 @@ type World struct { players map[string]*player } -func NewWorld(log *blammo.Log) *World { +func newWorld(log *blammo.Log) *world { bounds := math.CreateRect(10, 10) foyer := room{ Log: log.Child("foyer"), @@ -35,7 +35,7 @@ func NewWorld(log *blammo.Log) *World { behavior: doNothing{}, } log.Info("created foyer with bounds: %#v having width: %d height: %d area: %d", foyer.Rect, foyer.Width, foyer.Height, foyer.Area()) - return &World{ + return &world{ Log: log, rooms: []room{foyer}, done: make(chan bool), @@ -44,7 +44,7 @@ func NewWorld(log *blammo.Log) *World { } } -func (w *World) Run(hz int) { +func (w *world) run(hz int) { defer w.Info("simulation has exited run loop") period := time.Second / time.Duration(hz) @@ -94,13 +94,14 @@ func (w *World) Run(hz int) { } } -func (w *World) Stop() error { +func (w *world) stop() error { w.Info("stopping simulation") w.done <- true + w.Info("simulation stopped") return nil } -func (w *World) tick(d time.Duration) { +func (w *world) tick(d time.Duration) { for _, r := range w.rooms { r.update(d) }