worldhandling.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "math/rand"
  6. "net/http"
  7. glws "git.alfi.li/gamelang/frontend/webserver"
  8. gamelangpb "git.alfi.li/gamelang/protobuf/gamelang"
  9. "github.com/labstack/echo/v4"
  10. )
  11. func worldEndpoints(jg *JeopardyGameServer) []glws.Endpoint {
  12. endpoints := []glws.Endpoint{}
  13. endpoints = append(endpoints, glws.Endpoint{"GET", "/world", func(ctx echo.Context) error {
  14. ok, _ := jg.webserver.CheckSess(ctx)
  15. if !ok {
  16. log.Print("/World: not logged in")
  17. return ctx.String(http.StatusUnauthorized, "not logged in")
  18. }
  19. data := struct {
  20. Worlds []gamelangpb.World
  21. }{
  22. Worlds: func() []gamelangpb.World {
  23. worlds := jg.wm.List()
  24. return worlds
  25. }(),
  26. }
  27. err := ctx.Render(http.StatusOK, "worldlobby", data)
  28. if err != nil {
  29. log.Print(err)
  30. }
  31. return err
  32. }})
  33. endpoints = append(endpoints, glws.Endpoint{"POST", "/world", func(ctx echo.Context) error {
  34. ok, _ := jg.webserver.CheckSess(ctx)
  35. if !ok {
  36. log.Print("/World: not logged in")
  37. return ctx.String(http.StatusUnauthorized, "not logged in")
  38. }
  39. worldname := ctx.FormValue("worldname")
  40. world := &gamelangpb.World{Name: worldname}
  41. lobbygame := CraftLobbygame(fmt.Sprintf("%s\uffff%s", world.GetName(), "lobby"))
  42. world.Games = []string{lobbygame.Name}
  43. log.Println("/World: creating world_\n", world)
  44. id := rand.Uint32()
  45. world.Id = id
  46. _, err := jg.wm.Create(*world)
  47. if err != nil {
  48. log.Println("error creating world", err)
  49. return ctx.String(http.StatusInternalServerError, "error creating world")
  50. }
  51. err = jg.jeopardymanager.Create(lobbygame)
  52. if err != nil {
  53. log.Println("error creating world", err)
  54. return ctx.String(http.StatusInternalServerError, "error creating world")
  55. }
  56. return ctx.Redirect(http.StatusFound, "/world")
  57. }})
  58. endpoints = append(endpoints, glws.Endpoint{"POST", "/world/join", func(ctx echo.Context) error {
  59. log.Print("join attemt")
  60. ok, user := jg.webserver.CheckSess(ctx)
  61. if !ok {
  62. log.Print("/World/join: not logged in")
  63. return ctx.String(http.StatusUnauthorized, "not logged in")
  64. }
  65. worldname := ctx.FormValue("worldname")
  66. log.Println("joining", user.Name, "to", worldname)
  67. joinworld := gamelangpb.World{Name: worldname, Users: []*gamelangpb.User{}}
  68. joinworld.Users = append(joinworld.Users, &user)
  69. err := jg.wm.Join(worldname, &user)
  70. if err != nil {
  71. log.Printf("error joining %s to %s\n%s", user.Name, worldname, err.Error())
  72. return ctx.String(501, "join failed")
  73. }
  74. log.Println("join of", user.Name, "to", worldname, "complete")
  75. return ctx.Redirect(302, "/world")
  76. }})
  77. return endpoints
  78. return endpoints
  79. }
  80. func worldHandler(jg JeopardyGameServer) []glwss.Handler{} {
  81. handler := []glwss.Handler{}
  82. handler = append(handler, glwss.Handler{MType: "world:create", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) {
  83. createWorld := gamelangpb.World{Name: msg.Payload}
  84. lobbygame := CraftLobbygame(fmt.Sprintf("%s\uffff%s", createWorld.GetName(), "lobby"))
  85. createWorld.Games = []string{lobbygame.Name}
  86. id := rand.Uint32()
  87. createWorld.Id = id
  88. _, err := jg.wm.Create(*&createWorld)
  89. if err != nil {
  90. remsg := glwss.WSMsg{Mtype: "world:create", Payload: "failed"}
  91. return remsg, err
  92. }
  93. err = jg.jeopardymanager.Create(lobbygame)
  94. if err != nil {
  95. remsg := glwss.WSMsg{Mtype: "world:create", Payload: "failed"}
  96. return remsg, err
  97. }
  98. log.Println("world:create created Lobbygame:\n", lobbygame)
  99. createworldJSON, _ := json.Marshal(createWorld)
  100. remsg := glwss.WSMsg{Mtype: "world:create", Payload: string(createworldJSON)}
  101. return remsg, nil
  102. }})
  103. handler = append(handler, glwss.Handler{MType: "world:remove", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) {
  104. err := jg.wm.Remove(msg.Payload)
  105. if err != nil {
  106. remsg := glwss.WSMsg{Mtype: "world:remove", Payload: "failed"}
  107. return remsg, err
  108. }
  109. remsg := glwss.WSMsg{Mtype: "world:remove", Payload: "success"}
  110. return remsg, nil
  111. }})
  112. handler = append(handler, glwss.Handler{MType: "world:join", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) {
  113. worldname := msg.Payload
  114. err := jg.wm.Join(worldname, &user)
  115. if err != nil {
  116. remsg := glwss.WSMsg{Mtype: "world:join", Payload: "failed"}
  117. return remsg, err
  118. }
  119. remsg := glwss.WSMsg{Mtype: "world:join", Payload: "success"}
  120. return remsg, nil
  121. }})
  122. handler = append(handler, glwss.Handler{MType: "world:list", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) {
  123. log.Print("world:list")
  124. worldlist := jg.wm.List()
  125. worldlistJSON, err := json.Marshal(worldlist)
  126. if err != nil {
  127. log.Print(err.Error())
  128. msg := glwss.WSMsg{Mtype: "world:list", Payload: "failed"}
  129. return msg, err
  130. }
  131. log.Print("world:list", "sending list")
  132. remsg := glwss.WSMsg{Mtype: "world:list", Payload: string(worldlistJSON)}
  133. return remsg, nil
  134. }})
  135. handler = append(handler, glwss.Handler{MType: "game:get", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) {
  136. log.Println("game:get new get request:\n\"", msg.Payload, "\"")
  137. var world gamelangpb.World
  138. worldname := msg.Payload
  139. worlds := jg.wm.List()
  140. for _, world = range worlds {
  141. if world.GetName() == worldname {
  142. log.Println("sending world\n", world)
  143. break
  144. }
  145. }
  146. log.Println("game:get got world:\n\"", world, "\"")
  147. lobbygame := gljeopardypb.Jeopardy{}
  148. commongame := gljeopardypb.Jeopardy{}
  149. usergame := gljeopardypb.Jeopardy{}
  150. for _, game := range world.GetGames() {
  151. log.Println("searching games", game)
  152. if game == fmt.Sprintf("%s\uffff%s", world.GetName(), "lobby") {
  153. log.Println("found lobbygame", game)
  154. searchGame := gljeopardypb.Jeopardy{Name: game}
  155. lobbygame = jg.jeopardymanager.Get(searchGame)
  156. }
  157. if game == fmt.Sprintf("%s\uffff%s", world.GetName(), "common") {
  158. log.Println("found commongame", game)
  159. searchGame := gljeopardypb.Jeopardy{Name: game}
  160. commongame = jg.jeopardymanager.Get(searchGame)
  161. }
  162. if user.Name == strings.Split(game, "\uffff")[1] {
  163. log.Println("found usergame", game)
  164. searchGame := gljeopardypb.Jeopardy{Name: game}
  165. usergame = jg.jeopardymanager.Get(searchGame)
  166. break
  167. }
  168. }
  169. returngame := gljeopardypb.Jeopardy{}
  170. if usergame.Name == fmt.Sprintf("%s\uffff%s", world.GetName(), user.Name) {
  171. log.Println("sending usergame", usergame.Name)
  172. returngame = usergame
  173. } else if commongame.Name == fmt.Sprintf("%s\uffff%s", world.GetName(), "common") {
  174. log.Println("sending commongame", commongame.Name)
  175. returngame = commongame
  176. } else if lobbygame.Name == fmt.Sprintf("%s\uffff%s", world.GetName(), "lobby") {
  177. log.Println("sending lobbygame", lobbygame.Name)
  178. returngame = lobbygame
  179. } else {
  180. // if get returned empty game
  181. returngame = CraftLobbygame(fmt.Sprintf("%s\uffff%s", world.GetName(), "lobby"))
  182. jg.jeopardymanager.Create(returngame)
  183. log.Print("could not find lobbygame, so created one")
  184. }
  185. gameJSON, err := json.Marshal(returngame)
  186. if err != nil {
  187. remsg := glwss.WSMsg{Mtype: "game:get", Payload: "failed"}
  188. return remsg, err
  189. }
  190. log.Println("game:get sending game:\n", string(gameJSON))
  191. remsg := glwss.WSMsg{Mtype: "game:get", Payload: string(gameJSON)}
  192. return remsg, nil
  193. }})
  194. handler = append(handler, glwss.Handler{MType: "game:start", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) {
  195. log.Println("game:start new start request:\n", msg.Payload)
  196. startgame := gljeopardypb.Jeopardy{}
  197. err := json.Unmarshal([]byte(msg.Payload), &startgame)
  198. if err != nil {
  199. log.Printf("game:start - err unmarshalling startgame \"%s\"\n%s", msg, err.Error())
  200. remsg := glwss.WSMsg{Mtype: "game:start", Payload: "failed"}
  201. return remsg, err
  202. }
  203. var startworld gamelangpb.World
  204. worlds := jg.wm.List()
  205. for _, startworld = range worlds {
  206. if startworld.GetName() == strings.Split(startgame.Name, "\uffff")[0] {
  207. log.Println("sending world\n", startworld)
  208. break
  209. }
  210. }
  211. if err != nil {
  212. log.Printf("game:start - err unmarshalling startworld \"%s\"\n%s", msg, err.Error())
  213. remsg := glwss.WSMsg{Mtype: "game:start", Payload: "failed"}
  214. return remsg, err
  215. }
  216. // start game
  217. for _, option := range startgame.Options {
  218. if option.Key == "common game" && option.Bool {
  219. newGame := jg.jeopardymanager.CraftGame(rand.Uint32(), fmt.Sprintf("%s\uffffcommon", startworld.Name), startgame.Options...)
  220. jg.jeopardymanager.Create(*newGame)
  221. jg.wm.AddGame(startworld.Name, startworld.Name)
  222. jsonGame, err := json.Marshal(newGame)
  223. if err != nil {
  224. log.Printf("write: err marshalling game \"%s\"\n%s", msg, err.Error())
  225. }
  226. remsg := glwss.WSMsg{Mtype: "game:get", Payload: string(jsonGame)}
  227. if err != nil {
  228. log.Printf("write: err marshalling msg \"%s\"\n%s", msg, err.Error())
  229. }
  230. for _, user := range startworld.Users {
  231. go jg.wssserver.Write(user.Name, remsg)
  232. }
  233. }
  234. }
  235. remsg := glwss.WSMsg{Mtype: "game:start", Payload: "sucess"}
  236. return remsg, nil
  237. }})
  238. handler = append(handler, glwss.Handler{MType: "game:mod", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) {
  239. modgame := &gljeopardypb.Jeopardy{}
  240. err := json.Unmarshal([]byte(msg.Payload), modgame)
  241. if err != nil {
  242. log.Printf("game:mod - err unmarshalling msg \"%s\"\n%s", msg, err.Error())
  243. remsg := glwss.WSMsg{Mtype: "game:mod", Payload: "failed"}
  244. return remsg, nil
  245. }
  246. jg.jeopardymanager.Modify(*modgame)
  247. var world gamelangpb.World
  248. worlds := jg.wm.List()
  249. for _, world = range worlds {
  250. if world.GetName() == strings.Split(modgame.Name, "\uffff")[0] {
  251. log.Println("sending world\n", world)
  252. break
  253. }
  254. }
  255. if err != nil {
  256. log.Printf("game:mod - err getting world msg \"%s\"\n%s", msg, err.Error())
  257. remsg := glwss.WSMsg{Mtype: "game:mod", Payload: "failed"}
  258. return remsg, nil
  259. }
  260. notify := glwss.WSMsg{Mtype: "game:get", Payload: msg.Payload}
  261. for _, user := range world.Users {
  262. go jg.wssserver.Write(user.Name, notify)
  263. }
  264. jg.jeopardymanager.CheckWin()
  265. remsg := glwss.WSMsg{Mtype: "game:mod", Payload: "success"}
  266. return remsg, nil
  267. }})
  268. handler = append(handler, glwss.Handler{MType: "game:event", Callback: func(msg glwss.WSMsg, user gamelangpb.User) (glwss.WSMsg, error) {
  269. newevent := &gljeopardypb.Event{}
  270. err := json.Unmarshal([]byte(msg.Payload), newevent)
  271. if err != nil {
  272. log.Printf("game:event - err unmarshalling msg \"%s\"\n%s", msg, err.Error())
  273. remsg := glwss.WSMsg{Mtype: "game:event", Payload: "failed"}
  274. return remsg, nil
  275. }
  276. newevent.Username = user.Name
  277. log.Println("game:event new event", newevent)
  278. worldgamename := strings.Split(newevent.Gamename, "\uffff")
  279. worldname := worldgamename[0]
  280. gamename := worldgamename[1]
  281. // if the game is not a common game add all games from that world to neighborgames
  282. if gamename != "common" {
  283. var world gamelangpb.World
  284. worlds := jg.wm.List()
  285. for _, world = range worlds {
  286. if world.GetName() == worldname {
  287. log.Println("sending world\n", world)
  288. break
  289. }
  290. }
  291. if err != nil {
  292. log.Printf("workNotifications - err getting world msg \"%s\"\n%s", worldname, err.Error())
  293. remsg := glwss.WSMsg{Mtype: "game:mod", Payload: "failed"}
  294. return remsg, nil
  295. }
  296. for _, game := range world.Games {
  297. if strings.Split(game, "\uffff")[1] != "lobby" {
  298. newevent.Neighborgames = append(newevent.Neighborgames, game)
  299. }
  300. }
  301. }
  302. err = jg.jeopardymanager.HandleEvent(*newevent)
  303. if err != nil {
  304. if err.Error() == "game finished" {
  305. reevent := gljeopardypb.Event{Type: "Win", Gamename: newevent.Gamename}
  306. eventJson, err := json.Marshal(reevent)
  307. if err != nil {
  308. log.Printf("workNotifications - err marshalling event \"%s\"\n%s", reevent, err.Error())
  309. }
  310. notify := glwss.WSMsg{Mtype: "game:event", Payload: string(eventJson)}
  311. return notify, nil
  312. }
  313. return glwss.WSMsg{Mtype: "game:event", Payload: "failed"}, err
  314. }
  315. remsg := glwss.WSMsg{Mtype: "game:event", Payload: "success"}
  316. jg.jeopardymanager.CheckWin()
  317. return remsg, nil
  318. }})
  319. return handler
  320. }