diff options
Diffstat (limited to 'pages/game.tsx')
| -rw-r--r-- | pages/game.tsx | 291 | 
1 files changed, 142 insertions, 149 deletions
| diff --git a/pages/game.tsx b/pages/game.tsx index 58eb639..2103c38 100644 --- a/pages/game.tsx +++ b/pages/game.tsx @@ -1,7 +1,8 @@ -import { CSSProperties, Component } from 'react'; -import { io as socket, Socket } from 'socket.io-client'; +import { CSSProperties, useState, useEffect } from 'react'; +import { io as socket } from 'socket.io-client';  import axios from 'axios';  import * as cookies from 'react-cookies'; +import { useRouter } from 'next/router';  import { NavBar } from '../components/navbar';  import { CenteredPage } from '../components/page'; @@ -15,106 +16,86 @@ import WifiTetheringRoundedIcon from '@material-ui/icons/WifiTetheringRounded';  import LinkRoundedIcon from '@material-ui/icons/LinkRounded';  import RefreshIcon from '@material-ui/icons/Refresh'; -interface VoerGameProps { +var io = socket(); + +function VoerGame(props: {  	gameID: string; -	token: string;  	active: boolean;  	player1: boolean; -} +}) { +	var width = 7; +	var height = 6; -class VoerGame extends Component<VoerGameProps> { -	constructor(props: VoerGameProps) { -		super(props); +	var [ioListeners, setIoListeners] = useState(false); +	var [turn, setTurn] = useState(true); +	// var [winPositions, setWinPositions] = useState<Array<Array<number>>>([]); +	var [outcome, setOutcome] = useState(-1); +	var [board, setBoard] = useState<Array<number>>([...Array(width * height)].map(() => 0)); -		if (typeof document === "undefined") return; -		this.io = socket(); +	useEffect(() => { +		if (ioListeners) return; -		this.io.on("connect", () => console.log("connect")); -		this.io.on("disconnect", () => console.log("disconnect")); +		io.on("connect", () => console.log("connect")); +		io.on("disconnect", () => console.log("disconnect")); -		this.io.on("fieldUpdate", (data: { field: string }) => { -			this.setState({ board: data.field.split("").map(i => Number(i)) }); +		io.on("fieldUpdate", (data: { field: string }) => { +			setBoard(data.field.split("").map(i => Number(i))); //FIXME: Doesn't work for some fucking reason +			console.log(board); +			console.log(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]}`);  		}); -		this.io.on("turnUpdate", (data: { player1: boolean }) => this.setState({ turn: data.player1 })); - -		this.io.on("finish", (data: { -			winPositions: Array<Array<number>> -			boardFull: boolean }) => { +		io.on("turnUpdate", (data: { player1: boolean }) => setTurn(data.player1)); -			this.setState({ winPositions: data.winPositions }); +		io.on("finish", (data: { +				winPositions: Array<Array<number>> +				boardFull: boolean +				winner: number +			}) => { +			// setWinPositions(data.winPositions); -			var outcome = -1; -			if (data.winPositions.length > 0) outcome = this.state.board[data.winPositions[0][0]]; -			if (data.boardFull) outcome = 0; -			this.setState({ outcome }); +			if (data.boardFull) setOutcome(0); +			if (data.winPositions.length > 0) setOutcome(board[data.winPositions[0][0]]);  		}); -		this.io.on("resign", () => { +		io.on("resign", () => {  			alert("resign")  		}); -	} - -	io: Socket; - -	width = 7; -	height = 6; - -	state: { -		userID: string; -		turn: boolean; -		winPositions: Array<Array<number>>; -		outcome: number; -		board: Array<number>; -		saidHello: boolean; -	} = { -		userID: "", -		turn: true, -		winPositions: [], -		outcome: -1, -		board: [], -		saidHello: false, -	}; - -	board = [...Array(this.width * this.height)].map(() => 0); - -	move(column: number) { -		this.io.emit("newMove", { -			move: column, -			token: this.props.token, -			game_id: this.props.gameID -		}); -	} -	render() { -		this.props.active && this.io.emit("registerGameListener", { game_id: this.props.gameID }); -		return <div style={{ -			position: "relative", -			top: "50%", -			transform: "translateY(-50%)", -			maxWidth: "100vh", -			margin: "0 auto" -		}}> -			<VoerBord -				width={this.width} height={this.height} -				onMove={m => this.move(m % this.width + 1)} -				active={this.props.active == true && this.state.outcome == -1} -			/> -			<GameBar -				turn={this.state.turn} -				player1={this.props.player1} -				active={this.props.active} -				resignFunction={() => {this.io.emit("resign", { game_id: this.props.gameID })}} -			/> -			<GameOutcomeDialog -				outcome={this.state.outcome} -				player={this.props.player1 ? 1 : 2} -				visible={this.state.outcome != -1} -			/> -		</div> -	} +		setIoListeners(true); +	}); + +	return <div style={{ +		position: "relative", +		top: "50%", +		transform: "translateY(-50%)", +		maxWidth: "100vh", +		margin: "0 auto" +	}}> +		<VoerBord +			width={width} height={height} +			onMove={move => { +				io.emit("newMove", { +					move: move % width + 1, +					token: cookies.load("token"), +					game_id: props.gameID +				}); +			}} +			active={props.active && outcome == -1} +		/> +		<GameBar +			turn={turn} +			player1={props.player1} +			active={props.active} +			resignFunction={() => {this.io.emit("resign", { game_id: props.gameID })}} +		/> +		<GameOutcomeDialog +			outcome={outcome} +			player={props.player1 ? 1 : 2} +			visible={outcome != -1} +		/> +	</div>  }  function GameOutcomeDialog(props: { @@ -181,73 +162,85 @@ var InviteButtonLabelStyle: CSSProperties = {  	userSelect: "none"  } -export default class GamePage extends Component { -	constructor(props: {}) { -		super(props); - -		if (typeof document === "undefined") return; -		// gert +export default function GamePage() { +	var [ioListeners, setIoListeners] = useState(false); +	var [gameID, setGameID] = useState(""); +	var [player1, setPlayer1] = useState(true); +	var [active, setActive] = useState(false); +	var gameIDUrl = useRouter().query["id"] as string; + +	if (gameIDUrl && gameIDUrl != gameID) { +		// join game +		axios.request<{ id: string, player_1: boolean }>({ +			method: "post", +			url: "/api/game/accept", +			headers: {"content-type": "application/json"}, +			data: { id: gameIDUrl } +		}) +		.then(() => { +			setActive(true); +			io.emit("registerGameListener", { game_id: gameIDUrl }); +		}) +		.catch(() => {}); + +		setGameID(gameIDUrl);  	} -	state: { -		gameID: string; -		token: string; -		player1: boolean; -	} = { -		gameID: "", -		token: "", -		player1: true -	} - -	render() { -		return <div> -			<NavBar/> -			<CenteredPage width={900} style={{ height: "100vh" }}> -				<VoerGame -				active={!!this.state.gameID} -				gameID={this.state.gameID} -				token={this.state.token} -				player1={this.state.player1}/> -				<DialogBox title="Nieuw spel" style={{ display: !this.state.gameID ? "inline-block" : "none" }}> -					<CurrentGameSettings/> -					<div style={{ -						marginTop: 24, -						display: "grid", -						gridTemplateColumns: "1fr 1fr", -						gridGap: 24 +	useEffect(() => { +		if (ioListeners) return; + +		io.on("gameStart", () => setActive(true)); + +		setIoListeners(true); +	}); + +	return <div> +		<NavBar/> +		<CenteredPage width={900} style={{ height: "100vh" }}> +			<VoerGame +			active={active} +			gameID={gameID} +			player1={player1}/> +			<DialogBox title="Nieuw spel" style={{ display: gameIDUrl || gameID ? "none" : "inline-block" }}> +				<CurrentGameSettings/> +				<div style={{ +					marginTop: 24, +					display: "grid", +					gridTemplateColumns: "1fr 1fr", +					gridGap: 24 +				}}> +					<Button style={InviteButtonStyle} onclick={() => { +						axios.request<{ id: string, player_1: boolean, game_started: boolean }>({ +							method: "post", +							url: "/api/game/random", +							headers: {"content-type": "application/json"}, +							data: {} +						}) +						.then(response => { +							setGameID(response.data.id); +							setPlayer1(response.data.player_1); +							io.emit("registerGameListener", { game_id: response.data.id }); +							if (response.data.game_started) setActive(true); +						}) +						.catch(() => {});  					}}> -						<Button style={InviteButtonStyle} onclick={() => { -							axios.request<{ id: string, player_1: boolean }>({ -								method: "post", -								url: "/api/game/random", -								headers: {"content-type": "application/json"}, -								data: {} -							}) -							.then(request => this.setState({ -								gameID: request.data.id, -								player1: request.data.player_1, -								token: cookies.load("token") -							})) -							.catch(() => {}); -						}}> -							<WifiTetheringRoundedIcon style={{ -								color: "var(--disk-b)", -								...InviteButtonIconStyle -							}}/> -							<h2 style={InviteButtonLabelStyle}>Willekeurige speler</h2> -						</Button> -						<Button style={InviteButtonStyle}> -							<LinkRoundedIcon style={{ -								color: "var(--disk-a)", -								...InviteButtonIconStyle -							}}/> -							<h2 style={InviteButtonLabelStyle}>Uitnodigen via link</h2> -						</Button> -					</div> -					<SearchBar label="Zoeken in vriendenlijst"/> -				</DialogBox> -			</CenteredPage> -		</div> -	} +						<WifiTetheringRoundedIcon style={{ +							color: "var(--disk-b)", +							...InviteButtonIconStyle +						}}/> +						<h2 style={InviteButtonLabelStyle}>Willekeurige speler</h2> +					</Button> +					<Button style={InviteButtonStyle}> +						<LinkRoundedIcon style={{ +							color: "var(--disk-a)", +							...InviteButtonIconStyle +						}}/> +						<h2 style={InviteButtonLabelStyle}>Uitnodigen via link</h2> +					</Button> +				</div> +				<SearchBar label="Zoeken in vriendenlijst"/> +			</DialogBox> +		</CenteredPage> +	</div>  } |