diff options
-rw-r--r-- | api/events.py | 28 | ||||
-rw-r--r-- | api/game/random.py | 4 | ||||
-rw-r--r-- | api/game/socket.py | 27 | ||||
-rw-r--r-- | components/socketContext.tsx | 12 | ||||
-rw-r--r-- | pages/_app.tsx | 5 | ||||
-rw-r--r-- | pages/game.tsx | 29 | ||||
-rw-r--r-- | pages/index.tsx | 8 |
7 files changed, 80 insertions, 33 deletions
diff --git a/api/events.py b/api/events.py new file mode 100644 index 0000000..8974666 --- /dev/null +++ b/api/events.py @@ -0,0 +1,28 @@ +from flask import Blueprint, request, make_response +from flask_socketio import SocketIO, emit, Namespace, join_room, leave_room, rooms +from socket_io import io +from auth.login_token import token_login +from http import cookies + +from game.cleanup import set_interval +import time + +def get_token(environ): + cookie = environ.get("HTTP_COOKIE") + if not cookie: return None + parsed = cookies.SimpleCookie() + parsed.load(cookie) + token = parsed.get("token") + if not token: return None + return token.value + +@io.on("connect") +def connect(): + token = get_token(request.environ) + if not token: return + + user_id = token_login(token) + if not user_id: return + + join_room("user-" + user_id) + diff --git a/api/game/random.py b/api/game/random.py index bc9518d..54ab2a8 100644 --- a/api/game/random.py +++ b/api/game/random.py @@ -4,7 +4,7 @@ from randid import new_uuid import time import json import random -from game.socket import io, game, games, listeners +from game.socket import io, game, games from auth.login_token import token_login random_game = Blueprint('random', __name__) @@ -41,7 +41,7 @@ def index(): players = cursor.execute("select player_1_id, player_2_id from games where game_id = ?", [game_id]).fetchone() games[game_id] = game(game_id, io, players[0], players[1]) - games[game_id].send("gameStart", ""); + io.emit("gameStart", room=games[game_id].room) player_1 = False game_started = True diff --git a/api/game/socket.py b/api/game/socket.py index 0318e0b..60fea00 100644 --- a/api/game/socket.py +++ b/api/game/socket.py @@ -1,5 +1,5 @@ from flask import Blueprint, request, make_response -from flask_socketio import SocketIO, emit, Namespace +from flask_socketio import SocketIO, emit, Namespace, join_room from game.voerbak_connector import bord from auth.login_token import token_login from db import cursor, connection @@ -8,28 +8,23 @@ import json from socket_io import io games = {} -listeners = {} class game: def __init__(self, game_id, io, player_1_id, player_2_id): self.game_id = game_id + self.room = "game-" + game_id self.board = bord(7, 6) self.io = io self.player_1_id = player_1_id self.player_2_id = player_2_id - def send(self, message, data): - if not self.game_id in listeners: return - for listener in listeners[self.game_id]: - self.io.emit(message, data, room=listener) - def move(self, user_id, column): if user_id != self.player_1_id and user_id != self.player_2_id: return move = self.player_1_id if self.board.player_1 else self.player_2_id if user_id != move: return self.board.drop_fisje(column) - self.send("fieldUpdate", { "field": self.board.board }) + io.emit("fieldUpdate", { "field": self.board.board }, room=self.room) now = int( time.time() * 1000 ) cursor.execute("update games set last_activity = ?, moves = moves || ? || ',' where game_id = ?", [now, column, self.game_id]) @@ -40,18 +35,18 @@ class game: if not self.board.board_full: winner = self.board.board[int(self.board.win_positions[0][0])] outcome = "w" if winner == "2" else "l" - self.send("finish", { + io.emit("finish", { "winPositions": self.board.win_positions, "boardFull": self.board.board_full - }) + }, room=self.room) self.close("finished", outcome) return - self.send("turnUpdate", { "player1": self.board.player_1 }) + io.emit("turnUpdate", { "player1": self.board.player_1 }, room=self.room) def resign(self): self.board.kill_voerbak() - self.send("resign", "") + io.emit("resign", room=self.room) self.close("resign", "d") def close(self, new_status, outcome): @@ -71,7 +66,6 @@ class game: connection.commit() games.pop(self.game_id) - listeners.pop(self.game_id) @io.on("newMove") def new_move(data): @@ -102,7 +96,8 @@ def resign(data): @io.on("registerGameListener") def register_game_listener(data): - if not data["game_id"]: return - if not data["game_id"] in listeners: listeners[data["game_id"]] = set() - listeners[data["game_id"]].add(request.sid) + game_id = data.get("game_id") + if not game_id: return + + join_room("game-" + game_id) diff --git a/components/socketContext.tsx b/components/socketContext.tsx new file mode 100644 index 0000000..f493d73 --- /dev/null +++ b/components/socketContext.tsx @@ -0,0 +1,12 @@ +import { ReactNode, createContext } from 'react'; +import { io as socket, Socket } from 'socket.io-client'; + +export var SocketContext = createContext<{ io?: Socket }>({}); +export function SocketContextWrapper(props: { children?: ReactNode }) { + var io = socket(); + + return <SocketContext.Provider value={{ io }}> + { props.children } + </SocketContext.Provider> +} + diff --git a/pages/_app.tsx b/pages/_app.tsx index 1561eda..bfde0d7 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,6 +1,7 @@ import Head from 'next/head'; import { PreferencesContextWrapper } from '../components/preferencesContext'; import { ToastContextWrapper } from '../components/toast'; +import { SocketContextWrapper } from '../components/socketContext'; import '../styles/global.css'; import '../styles/dark.css'; @@ -26,7 +27,9 @@ export default function VierOpEenRijWebsite({ Component, pageProps }) { </Head> <PreferencesContextWrapper> <ToastContextWrapper> - <Component {...pageProps}/> + <SocketContextWrapper> + <Component {...pageProps}/> + </SocketContextWrapper> </ToastContextWrapper> </PreferencesContextWrapper> </div> diff --git a/pages/game.tsx b/pages/game.tsx index a7083a6..aa90588 100644 --- a/pages/game.tsx +++ b/pages/game.tsx @@ -1,8 +1,9 @@ -import { CSSProperties, useState, useEffect } from 'react'; -import { io as socket } from 'socket.io-client'; +import { CSSProperties, useState, useEffect, useContext } from 'react'; import axios from 'axios'; import * as cookies from 'react-cookies'; import { useRouter } from 'next/router'; +import { SocketContext } from '../components/socketContext'; +import { Socket } from 'socket.io-client'; import { NavBar } from '../components/navbar'; import { CenteredPage } from '../components/page'; @@ -16,12 +17,11 @@ import WifiTetheringRoundedIcon from '@material-ui/icons/WifiTetheringRounded'; import LinkRoundedIcon from '@material-ui/icons/LinkRounded'; import RefreshIcon from '@material-ui/icons/Refresh'; -var io = socket(); - function VoerGame(props: { gameID: string; active: boolean; player1: boolean; + io: Socket; }) { var width = 7; var height = 6; @@ -35,18 +35,18 @@ function VoerGame(props: { useEffect(() => { if (ioListeners) return; - io.on("connect", () => console.log("connect")); - io.on("disconnect", () => console.log("disconnect")); + props.io.on("connect", () => console.log("connect")); + props.io.on("disconnect", () => console.log("disconnect")); - io.on("fieldUpdate", (data: { field: string }) => { + props.io.on("fieldUpdate", (data: { field: string }) => { board = data.field.split("").map(i => Number(i)); for(let i = 0; i < data.field.length; i++) document.getElementById(`pos-${i}`).parentNode.children.item(1).classList.add(`state-${data.field[i]}`); }); - io.on("turnUpdate", (data: { player1: boolean }) => setTurn(data.player1)); + props.io.on("turnUpdate", (data: { player1: boolean }) => setTurn(data.player1)); - io.on("finish", (data: { + props.io.on("finish", (data: { winPositions: Array<Array<number>> boardFull: boolean winner: number @@ -57,7 +57,7 @@ function VoerGame(props: { if (data.winPositions.length > 0) setOutcome(board[data.winPositions[0][0]]); }); - io.on("resign", () => { + props.io.on("resign", () => { alert("resign") }); @@ -74,7 +74,7 @@ function VoerGame(props: { <VoerBord width={width} height={height} onMove={move => { - io.emit("newMove", { + props.io.emit("newMove", { move: move % width + 1, token: cookies.load("token"), game_id: props.gameID @@ -86,7 +86,7 @@ function VoerGame(props: { turn={turn} player1={props.player1} active={props.active} - resignFunction={() => {io.emit("resign", { game_id: props.gameID })}} + resignFunction={() => { props.io.emit("resign", { game_id: props.gameID }) }} /> <GameOutcomeDialog outcome={outcome} @@ -173,6 +173,8 @@ export default function GamePage() { var [active, setActive] = useState(false); var gameIDUrl = useRouter().query["id"] as string; + var { io } = useContext(SocketContext); + if (gameIDUrl && gameIDUrl != gameID) { // join game axios.request<{ id: string, player_1: boolean }>({ @@ -204,7 +206,8 @@ export default function GamePage() { <VoerGame active={active} gameID={gameID} - player1={player1}/> + player1={player1} + io={io}/> <DialogBox title="Nieuw spel" style={{ display: gameIDUrl || gameID ? "none" : "inline-block" }} diff --git a/pages/index.tsx b/pages/index.tsx index 266a3f4..dfb14e6 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,6 +1,7 @@ -import { CSSProperties, useState, useEffect } from 'react'; +import { CSSProperties, useState, useEffect, useContext } from 'react'; import axios from 'axios'; import { userInfo, userGameTotals, userGames } from '../api/api'; +import { SocketContext } from '../components/socketContext'; import { NavBar } from '../components/navbar'; import { CenteredPage, PageTitle } from '../components/page'; @@ -120,6 +121,11 @@ export default function HomePage() { var server = typeof window === "undefined"; var loggedIn = !server && document.cookie.includes("token"); + var { io } = useContext(SocketContext); + useEffect(() => { + io.on("connect", () => { console.log("gert") }); + }, []); + var [userInfo, setUserInfo] = useState<userInfo>(); var [gameInfo, setGameInfo] = useState<userGames>(); |