StateRouter.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import React, { useEffect, useState } from 'react';
  2. import useWebsocket, { WebsocketStatus } from "./util/useWebsocket";
  3. import LoadingJoker from "./LoadingJoker";
  4. import LandingPage from "./LandingPage";
  5. import Lobby from "./Lobby";
  6. import Game from "./Game";
  7. import deck from "./img/deck.svg";
  8. export const SiteState = {
  9. // Frontend only
  10. WAITING_FOR_WS: "waiting_for_ws",
  11. JOIN_LINK: "join_link",
  12. // Lobby
  13. START: "start",
  14. PICK_COLOR: "pick_color",
  15. // Dealing
  16. DEAL: "deal",
  17. DEAL_OTHER: "deal_other",
  18. // Hand
  19. SWAP_CARD: "swap_card",
  20. SWAP_CARD_OTHERS: "swap_card_others",
  21. PLAY_CARD: "play_card",
  22. PLAY_CARD_OTHER: "play_card_other",
  23. }
  24. export const Commands = {
  25. NEW_GAME: "new_game",
  26. JOIN_GAME: "join_game",
  27. PICK_COLOR: "pick_color",
  28. DEAL: "deal",
  29. SWAP_CARD: "swap_card",
  30. PLAY_CARD: "play_card",
  31. READY: "ready",
  32. UNDO_CARD: "undo_card",
  33. PASS: "pass",
  34. }
  35. export default function StateRouter() {
  36. const [websocket, websocketStatus] = useWebsocket();
  37. const path = window.location.pathname;
  38. const path_code = path === "/" ?
  39. null :
  40. parseInt(path.split("/")[1]);
  41. console.log({path, path_code});
  42. const initial_state = path_code === null ?
  43. { state: SiteState.WAITING_FOR_WS } :
  44. { state: SiteState.JOIN_LINK, game_code: path_code };
  45. const send = websocketStatus === WebsocketStatus.CONNECTED ?
  46. (data) => websocket.send(JSON.stringify(data)) :
  47. (data) => console.error(`Cannot send: websocket is in state ${websocketStatus}, data:`, data);
  48. const [message, setMessage] = useState(initial_state);
  49. const { state, options, game_code, ...args } = message;
  50. useEffect(() => {
  51. if (websocketStatus === WebsocketStatus.CONNECTED && state === SiteState.JOIN_LINK) {
  52. send({
  53. code: Commands.JOIN_GAME,
  54. game_code,
  55. text: "Neem deel aan spel",
  56. })
  57. }
  58. }, [websocketStatus, message])
  59. useEffect(() => {
  60. if (game_code !== undefined && game_code !== null) {
  61. window.history.pushState(null, "", `/${game_code}`)
  62. }
  63. if (isNaN(path_code)) {
  64. window.history.pushState(null, "", "/")
  65. }
  66. }, [message])
  67. useEffect(() => {
  68. switch (websocketStatus) {
  69. case WebsocketStatus.RECONNECTING:
  70. case WebsocketStatus.CONNECTING:
  71. case WebsocketStatus.CONNECTED:
  72. const handler = (event) => {
  73. setMessage(JSON.parse(event.data))
  74. };
  75. websocket.addEventListener("message", handler)
  76. return () => websocket.removeEventListener("message", handler)
  77. }
  78. }, [websocketStatus]
  79. )
  80. switch (websocketStatus) {
  81. case WebsocketStatus.DISCONNECTING:
  82. case WebsocketStatus.RECONNECTING:
  83. case WebsocketStatus.CONNECTING:
  84. return <LoadingJoker size={44}/>;
  85. case WebsocketStatus.ERROR:
  86. case WebsocketStatus.DISCONNECTED:
  87. return "Something went wrong :/";
  88. case WebsocketStatus.CONNECTED:
  89. break;
  90. default:
  91. console.error("Unknown websocketStatus", websocketStatus);
  92. return "Something went wrong :/";
  93. }
  94. // Websocket is now connected
  95. switch (state) {
  96. case SiteState.WAITING_FOR_WS:
  97. return <LoadingJoker size={44}/>
  98. case SiteState.START:
  99. return <LandingPage message={message}
  100. newGame={() => send({
  101. code: Commands.NEW_GAME,
  102. text: "Begin nieuw spel",
  103. })}
  104. joinGame={(code) => send({
  105. code: Commands.JOIN_GAME,
  106. game_code: 3936,
  107. text: "Neem deel aan spel 3936",
  108. })}/>
  109. case SiteState.PICK_COLOR:
  110. return <Lobby message={message}
  111. pickColor={(color) => send({
  112. code: Commands.PICK_COLOR,
  113. text: "Kies kleur",
  114. color
  115. })}
  116. deal={() => send({
  117. code: Commands.DEAL,
  118. text: "Deel",
  119. })}/>
  120. case SiteState.SWAP_CARD:
  121. case SiteState.SWAP_CARD_OTHERS:
  122. case SiteState.PLAY_CARD:
  123. case SiteState.PLAY_CARD_OTHER:
  124. return <Game message={message}
  125. swapCard={(card) => send({
  126. code: Commands.SWAP_CARD,
  127. text: "Wissel kaart",
  128. card,
  129. })}
  130. playCard={(card) => send({
  131. code: Commands.PLAY_CARD,
  132. text: "Speel kaart",
  133. card,
  134. })}
  135. confirmPlay={() => send({
  136. code: Commands.READY,
  137. text: "Klaar/Bevestig kaart",
  138. })}
  139. undoPlay={() => send({
  140. code: Commands.UNDO_CARD,
  141. text: "Terug/Neem kaart terug",
  142. })}/>
  143. case SiteState.DEAL:
  144. return <div className="row justify-content-center flex-md-column my-2">
  145. <h1>Klik om te delen</h1><br/>
  146. <div className="btn btn-link" onClick={() => send({
  147. code: Commands.DEAL,
  148. text: "Delen",
  149. })}>
  150. <img src={deck} alt="kaartenstapel"/><br/><span>Delen</span>
  151. </div>
  152. </div>;
  153. case SiteState.DEAL_OTHER:
  154. return <h1>Wachten tot {args.current_player.color}({args.current_player.name}) heeft gedeeld</h1>
  155. default:
  156. return `state: ${state}, wsstatus: ${websocketStatus}`
  157. }
  158. }