package main import ( "fmt" "log" "math/rand" "net/http" glws "git.alfi.li/gamelang/frontend/webserver" gamelangpb "git.alfi.li/gamelang/protobuf/gamelang" "github.com/labstack/echo/v4" ) func worldEndpoints(jg *JeopardyGameServer) []glws.Endpoint { endpoints := []glws.Endpoint{} endpoints = append(endpoints, glws.Endpoint{"GET", "/world", func(ctx echo.Context) error { ok, _ := jg.webserver.CheckSess(ctx) if !ok { log.Print("/World: not logged in") return ctx.String(http.StatusUnauthorized, "not logged in") } data := struct { Worlds []gamelangpb.World }{ Worlds: func() []gamelangpb.World { worlds := jg.wm.List() return worlds }(), } err := ctx.Render(http.StatusOK, "worldlobby", data) if err != nil { log.Print(err) } return err }}) endpoints = append(endpoints, glws.Endpoint{"POST", "/world", func(ctx echo.Context) error { ok, _ := jg.webserver.CheckSess(ctx) if !ok { log.Print("/World: not logged in") return ctx.String(http.StatusUnauthorized, "not logged in") } worldname := ctx.FormValue("worldname") world := &gamelangpb.World{Name: worldname} lobbygame := CraftLobbygame(fmt.Sprintf("%s\uffff%s", world.GetName(), "lobby")) world.Games = []string{lobbygame.Name} log.Println("/World: creating world_\n", world) id := rand.Uint32() world.Id = id _, err := jg.wm.Create(*world) if err != nil { log.Println("error creating world", err) return ctx.String(http.StatusInternalServerError, "error creating world") } err = jg.jeopardymanager.Create(lobbygame) if err != nil { log.Println("error creating world", err) return ctx.String(http.StatusInternalServerError, "error creating world") } return ctx.Redirect(http.StatusFound, "/world") }}) endpoints = append(endpoints, glws.Endpoint{"POST", "/world/join", func(ctx echo.Context) error { log.Print("join attemt") ok, user := jg.webserver.CheckSess(ctx) if !ok { log.Print("/World/join: not logged in") return ctx.String(http.StatusUnauthorized, "not logged in") } worldname := ctx.FormValue("worldname") log.Println("joining", user.Name, "to", worldname) joinworld := gamelangpb.World{Name: worldname, Users: []*gamelangpb.User{}} joinworld.Users = append(joinworld.Users, &user) err := jg.wm.Join(worldname, &user) if err != nil { log.Printf("error joining %s to %s\n%s", user.Name, worldname, err.Error()) return ctx.String(501, "join failed") } log.Println("join of", user.Name, "to", worldname, "complete") return ctx.Redirect(302, "/world") }}) return endpoints return endpoints } func worldHandler(jg JeopardyGameServer) []glwss.Handler{} { handler := []glwss.Handler{} handler = append(handler, glwss.Handler{MType: "world:create", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) { createWorld := gamelangpb.World{Name: msg.Payload} lobbygame := CraftLobbygame(fmt.Sprintf("%s\uffff%s", createWorld.GetName(), "lobby")) createWorld.Games = []string{lobbygame.Name} id := rand.Uint32() createWorld.Id = id _, err := jg.wm.Create(*&createWorld) if err != nil { remsg := glwss.WSMsg{Mtype: "world:create", Payload: "failed"} return remsg, err } err = jg.jeopardymanager.Create(lobbygame) if err != nil { remsg := glwss.WSMsg{Mtype: "world:create", Payload: "failed"} return remsg, err } log.Println("world:create created Lobbygame:\n", lobbygame) createworldJSON, _ := json.Marshal(createWorld) remsg := glwss.WSMsg{Mtype: "world:create", Payload: string(createworldJSON)} return remsg, nil }}) handler = append(handler, glwss.Handler{MType: "world:remove", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) { err := jg.wm.Remove(msg.Payload) if err != nil { remsg := glwss.WSMsg{Mtype: "world:remove", Payload: "failed"} return remsg, err } remsg := glwss.WSMsg{Mtype: "world:remove", Payload: "success"} return remsg, nil }}) handler = append(handler, glwss.Handler{MType: "world:join", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) { worldname := msg.Payload err := jg.wm.Join(worldname, &user) if err != nil { remsg := glwss.WSMsg{Mtype: "world:join", Payload: "failed"} return remsg, err } remsg := glwss.WSMsg{Mtype: "world:join", Payload: "success"} return remsg, nil }}) handler = append(handler, glwss.Handler{MType: "world:list", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) { log.Print("world:list") worldlist := jg.wm.List() worldlistJSON, err := json.Marshal(worldlist) if err != nil { log.Print(err.Error()) msg := glwss.WSMsg{Mtype: "world:list", Payload: "failed"} return msg, err } log.Print("world:list", "sending list") remsg := glwss.WSMsg{Mtype: "world:list", Payload: string(worldlistJSON)} return remsg, nil }}) handler = append(handler, glwss.Handler{MType: "game:get", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) { log.Println("game:get new get request:\n\"", msg.Payload, "\"") var world gamelangpb.World worldname := msg.Payload worlds := jg.wm.List() for _, world = range worlds { if world.GetName() == worldname { log.Println("sending world\n", world) break } } log.Println("game:get got world:\n\"", world, "\"") lobbygame := gljeopardypb.Jeopardy{} commongame := gljeopardypb.Jeopardy{} usergame := gljeopardypb.Jeopardy{} for _, game := range world.GetGames() { log.Println("searching games", game) if game == fmt.Sprintf("%s\uffff%s", world.GetName(), "lobby") { log.Println("found lobbygame", game) searchGame := gljeopardypb.Jeopardy{Name: game} lobbygame = jg.jeopardymanager.Get(searchGame) } if game == fmt.Sprintf("%s\uffff%s", world.GetName(), "common") { log.Println("found commongame", game) searchGame := gljeopardypb.Jeopardy{Name: game} commongame = jg.jeopardymanager.Get(searchGame) } if user.Name == strings.Split(game, "\uffff")[1] { log.Println("found usergame", game) searchGame := gljeopardypb.Jeopardy{Name: game} usergame = jg.jeopardymanager.Get(searchGame) break } } returngame := gljeopardypb.Jeopardy{} if usergame.Name == fmt.Sprintf("%s\uffff%s", world.GetName(), user.Name) { log.Println("sending usergame", usergame.Name) returngame = usergame } else if commongame.Name == fmt.Sprintf("%s\uffff%s", world.GetName(), "common") { log.Println("sending commongame", commongame.Name) returngame = commongame } else if lobbygame.Name == fmt.Sprintf("%s\uffff%s", world.GetName(), "lobby") { log.Println("sending lobbygame", lobbygame.Name) returngame = lobbygame } else { // if get returned empty game returngame = CraftLobbygame(fmt.Sprintf("%s\uffff%s", world.GetName(), "lobby")) jg.jeopardymanager.Create(returngame) log.Print("could not find lobbygame, so created one") } gameJSON, err := json.Marshal(returngame) if err != nil { remsg := glwss.WSMsg{Mtype: "game:get", Payload: "failed"} return remsg, err } log.Println("game:get sending game:\n", string(gameJSON)) remsg := glwss.WSMsg{Mtype: "game:get", Payload: string(gameJSON)} return remsg, nil }}) handler = append(handler, glwss.Handler{MType: "game:start", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) { log.Println("game:start new start request:\n", msg.Payload) startgame := gljeopardypb.Jeopardy{} err := json.Unmarshal([]byte(msg.Payload), &startgame) if err != nil { log.Printf("game:start - err unmarshalling startgame \"%s\"\n%s", msg, err.Error()) remsg := glwss.WSMsg{Mtype: "game:start", Payload: "failed"} return remsg, err } var startworld gamelangpb.World worlds := jg.wm.List() for _, startworld = range worlds { if startworld.GetName() == strings.Split(startgame.Name, "\uffff")[0] { log.Println("sending world\n", startworld) break } } if err != nil { log.Printf("game:start - err unmarshalling startworld \"%s\"\n%s", msg, err.Error()) remsg := glwss.WSMsg{Mtype: "game:start", Payload: "failed"} return remsg, err } // start game for _, option := range startgame.Options { if option.Key == "common game" && option.Bool { newGame := jg.jeopardymanager.CraftGame(rand.Uint32(), fmt.Sprintf("%s\uffffcommon", startworld.Name), startgame.Options...) jg.jeopardymanager.Create(*newGame) jg.wm.AddGame(startworld.Name, startworld.Name) jsonGame, err := json.Marshal(newGame) if err != nil { log.Printf("write: err marshalling game \"%s\"\n%s", msg, err.Error()) } remsg := glwss.WSMsg{Mtype: "game:get", Payload: string(jsonGame)} if err != nil { log.Printf("write: err marshalling msg \"%s\"\n%s", msg, err.Error()) } for _, user := range startworld.Users { go jg.wssserver.Write(user.Name, remsg) } } } remsg := glwss.WSMsg{Mtype: "game:start", Payload: "sucess"} return remsg, nil }}) handler = append(handler, glwss.Handler{MType: "game:mod", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) { modgame := &gljeopardypb.Jeopardy{} err := json.Unmarshal([]byte(msg.Payload), modgame) if err != nil { log.Printf("game:mod - err unmarshalling msg \"%s\"\n%s", msg, err.Error()) remsg := glwss.WSMsg{Mtype: "game:mod", Payload: "failed"} return remsg, nil } jg.jeopardymanager.Modify(*modgame) var world gamelangpb.World worlds := jg.wm.List() for _, world = range worlds { if world.GetName() == strings.Split(modgame.Name, "\uffff")[0] { log.Println("sending world\n", world) break } } if err != nil { log.Printf("game:mod - err getting world msg \"%s\"\n%s", msg, err.Error()) remsg := glwss.WSMsg{Mtype: "game:mod", Payload: "failed"} return remsg, nil } notify := glwss.WSMsg{Mtype: "game:get", Payload: msg.Payload} for _, user := range world.Users { go jg.wssserver.Write(user.Name, notify) } jg.jeopardymanager.CheckWin() remsg := glwss.WSMsg{Mtype: "game:mod", Payload: "success"} return remsg, nil }}) handler = append(handler, glwss.Handler{MType: "game:event", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) { newevent := &gljeopardypb.Event{} err := json.Unmarshal([]byte(msg.Payload), newevent) if err != nil { log.Printf("game:event - err unmarshalling msg \"%s\"\n%s", msg, err.Error()) remsg := glwss.WSMsg{Mtype: "game:event", Payload: "failed"} return remsg, nil } newevent.Username = user.Name log.Println("game:event new event", newevent) worldgamename := strings.Split(newevent.Gamename, "\uffff") worldname := worldgamename[0] gamename := worldgamename[1] // if the game is not a common game add all games from that world to neighborgames if gamename != "common" { var world gamelangpb.World worlds := jg.wm.List() for _, world = range worlds { if world.GetName() == worldname { log.Println("sending world\n", world) break } } if err != nil { log.Printf("workNotifications - err getting world msg \"%s\"\n%s", worldname, err.Error()) remsg := glwss.WSMsg{Mtype: "game:mod", Payload: "failed"} return remsg, nil } for _, game := range world.Games { if strings.Split(game, "\uffff")[1] != "lobby" { newevent.Neighborgames = append(newevent.Neighborgames, game) } } } err = jg.jeopardymanager.HandleEvent(*newevent) if err != nil { if err.Error() == "game finished" { reevent := gljeopardypb.Event{Type: "Win", Gamename: newevent.Gamename} eventJson, err := json.Marshal(reevent) if err != nil { log.Printf("workNotifications - err marshalling event \"%s\"\n%s", reevent, err.Error()) } notify := glwss.WSMsg{Mtype: "game:event", Payload: string(eventJson)} return notify, nil } return glwss.WSMsg{Mtype: "game:event", Payload: "failed"}, err } remsg := glwss.WSMsg{Mtype: "game:event", Payload: "success"} jg.jeopardymanager.CheckWin() return remsg, nil }}) return handler }