func New(ctx context.Context, total, diff chan []byte, actions chan sim.Action, port string) { var worldData []byte nextId := 0 newConns := make(chan webSocketDone) conns := map[int]chan []byte{} handleWebSocket := func(ws *websocket.Conn) { done := make(chan struct{}) ctx, cancel := context.WithCancel(context.Background()) newConns <- webSocketDone{ws, done, ctx, 0} for { var a sim.Action err := websocket.JSON.Receive(ws, &a) if err == io.EOF { cancel() break } else if err != nil { logrus.Error(err) break } logrus.Infof("Found a kind: %s", a.Kind) actions <- a } <-done logrus.Infof("Closing websocket: %v", ws) } handleLocalWebSocket := func(ws *websocket.Conn) { s := sim.NewState(500, 62) actions := make(chan sim.Action) species := s.AddSpecies(275, "", "Me") s.AddSpore(sim.Location{0, 100}, species) ss := s.StartSimulate(actions) defer s.StopSimulate() ctx, cancel := context.WithCancel(context.Background()) go func() { // First send the starting state ms := <-ss err := websocket.Message.Send(ws, ms.State) if err != nil { logrus.Error(err) } // Then send diffs for { select { case ms := <-ss: err := websocket.Message.Send(ws, ms.Diff) if err != nil { logrus.Error(err) } continue case <-ctx.Done(): } break } }() for { var a sim.Action err := websocket.JSON.Receive(ws, &a) if err == io.EOF { cancel() break } else if err != nil { logrus.Error(err) break } logrus.Infof("Found a kind: %s", a.Kind) actions <- a } } go func() { http.Handle("/global", websocket.Handler(handleWebSocket)) http.Handle("/local", websocket.Handler(handleLocalWebSocket)) // XXX SUPER SKETCH http.Handle("/", http.FileServer(http.Dir("../client"))) err := http.ListenAndServe(port, nil) if err != nil { logrus.Error(err) } }() for { select { case data := <-total: worldData = data case data := <-diff: // logrus.Infof("sending diff to %d clients with total %d", len(conns), nextId) for key, c := range conns { logrus.Infof("sending DIFF to %d", key) go func(b chan []byte) { b <- data }(c) } case wd := <-newConns: sendWorld(wd, worldData) c := make(chan []byte, 100) conns[nextId] = c id := nextId wd.id = id nextId++ go func() { sendDiffs(ctx, wd, c) close(wd.done) delete(conns, id) }() } } }
func main() { logrus.SetLevel(logrus.WarnLevel) ctx, cancel := context.WithCancel(context.Background()) defer cancel() total := make(chan []byte) diff := make(chan []byte) actions := make(chan sim.Action) s := sim.NewState(500, 125) spawnHeight := 50 species := s.AddSpecies(256, maxMeander, "Me") for i := 0; i < 10; i++ { s.AddSpore(sim.Location{rand.Intn(500), spawnHeight}, species) } species = s.AddSpecies(244, jakeRand, "Me") for i := 0; i < 10; i++ { s.AddSpore(sim.Location{rand.Intn(500), spawnHeight}, species) } species = s.AddSpecies(128, upUp, "Me") for i := 0; i < 10; i++ { s.AddSpore(sim.Location{rand.Intn(500), spawnHeight}, species) } species = s.AddSpecies(63, crystal, "Me") for i := 0; i < 10; i++ { s.AddSpore(sim.Location{rand.Intn(500), spawnHeight}, species) } species = s.AddSpecies(44, maxMemory, "Me") for i := 0; i < 10; i++ { s.AddSpore(sim.Location{rand.Intn(500), spawnHeight}, species) } species = s.AddSpecies(14, fearnLeft, "Me") for i := 0; i < 10; i++ { s.AddSpore(sim.Location{rand.Intn(500), spawnHeight}, species) } species = s.AddSpecies(1, coral, "Me") for i := 0; i < 10; i++ { s.AddSpore(sim.Location{rand.Intn(500), spawnHeight}, species) } species = s.AddSpecies(275, twistyUp, "Me") for i := 0; i < 10; i++ { s.AddSpore(sim.Location{rand.Intn(500), spawnHeight}, species) } species = s.AddSpecies(300, twistyLeft, "Me") for i := 0; i < 10; i++ { s.AddSpore(sim.Location{rand.Intn(500), spawnHeight}, species) } port := ":4444" logrus.Infof("Listening on port %s", port) go New(ctx, total, diff, actions, port) ss := s.StartSimulate(actions) for { ms := <-ss total <- ms.State diff <- ms.Diff } }