Commit 9d2a6016 authored by root's avatar root

production debug

parent ebe4288e
export const APP_URL = "/games/tictachack"
\ No newline at end of file
APP_URL=/games/tictachack
\ No newline at end of file
...@@ -2,6 +2,7 @@ import type { NextConfig } from "next"; ...@@ -2,6 +2,7 @@ import type { NextConfig } from "next";
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
/* config options here */ /* config options here */
basePath: '/games/tictachack'
}; };
export default nextConfig; export default nextConfig;
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev --turbopack", "dev": "next dev --turbopack -p 3001",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start -p 3001",
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
......
'use client'; 'use client';
import { useEffect, useState } from 'react'; import { useEffect, useState, Suspense } from 'react';
import { useSearchParams } from 'next/navigation'; import { useSearchParams } from 'next/navigation';
import { io, Socket } from 'socket.io-client'; import { io, Socket } from 'socket.io-client';
import GameBoard from '../components/GameBoard'; import GameBoard from '../components/GameBoard';
import PlayerInfo from '../components/PlayerInfo'; import PlayerInfo from '../components/PlayerInfo';
import GameInvite from '../components/GameInvite'; import GameInvite from '../components/GameInvite';
import { GameState, Player, GameMove } from '../types/game'; import { GameState } from '../types/game';
import {APP_URL} from '../../constants';
let socket: Socket; let socket: Socket;
export default function Home() { function Home() {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const [roomId, setRoomId] = useState<string>(''); const [roomId, setRoomId] = useState<string>('');
const [showInvite, setShowInvite] = useState(false); const [showInvite, setShowInvite] = useState(false);
...@@ -27,11 +28,12 @@ export default function Home() { ...@@ -27,11 +28,12 @@ export default function Home() {
const [turnTimeLeft, setTurnTimeLeft] = useState<number>(20000); const [turnTimeLeft, setTurnTimeLeft] = useState<number>(20000);
useEffect(() => { useEffect(() => {
const roomFromUrl = searchParams.get('room');
if (!socket) { if (!socket) {
socket = io({ socket = io({
path: '/api/socket', path: `${APP_URL}/api/socket`,
}); });
socket.on('connect', () => { socket.on('connect', () => {
...@@ -57,9 +59,12 @@ export default function Home() { ...@@ -57,9 +59,12 @@ export default function Home() {
}); });
} }
if (roomFromUrl) { if (searchParams) {
socket.emit('joinGame', { roomId: roomFromUrl }); const roomFromUrl = searchParams.get('room');
setRoomId(roomFromUrl); if (roomFromUrl) {
socket.emit('joinGame', { roomId: roomFromUrl });
setRoomId(roomFromUrl);
}
} }
return () => { return () => {
...@@ -72,8 +77,9 @@ export default function Home() { ...@@ -72,8 +77,9 @@ export default function Home() {
useEffect(() => { useEffect(() => {
let timer: NodeJS.Timeout; let timer: NodeJS.Timeout;
if (gameState.isYourTurn && gameState.turnStartTime) { if (gameState.isYourTurn && gameState.turnStartTime) {
const startTime = gameState.turnStartTime;
timer = setInterval(() => { timer = setInterval(() => {
const timeLeft = gameState.turnTimeLimit - (Date.now() - gameState.turnStartTime); const timeLeft = gameState.turnTimeLimit - (Date.now() - startTime);
setTurnTimeLeft(Math.max(0, timeLeft)); setTurnTimeLeft(Math.max(0, timeLeft));
if (timeLeft <= 0) { if (timeLeft <= 0) {
socket.emit('turnTimeout', { roomId }); socket.emit('turnTimeout', { roomId });
...@@ -84,7 +90,7 @@ export default function Home() { ...@@ -84,7 +90,7 @@ export default function Home() {
return () => clearInterval(timer); return () => clearInterval(timer);
}, [gameState.isYourTurn, gameState.turnStartTime, gameState.turnTimeLimit, roomId]); }, [gameState.isYourTurn, gameState.turnStartTime, gameState.turnTimeLimit, roomId]);
const handleCreateGame = () => { const handleCreateGame = () => {
socket.emit('createGame'); socket.emit('createGame');
socket.once('gameCreated', ({ roomId, gameState }: { roomId: string, gameState: GameState }) => { socket.once('gameCreated', ({ roomId, gameState }: { roomId: string, gameState: GameState }) => {
setRoomId(roomId); setRoomId(roomId);
...@@ -130,6 +136,7 @@ export default function Home() { ...@@ -130,6 +136,7 @@ export default function Home() {
} }
return ( return (
<Suspense>
<div className="relative min-h-screen bg-gray-900 text-white"> <div className="relative min-h-screen bg-gray-900 text-white">
{showInvite && <GameInvite roomId={roomId} />} {showInvite && <GameInvite roomId={roomId} />}
...@@ -200,5 +207,16 @@ export default function Home() { ...@@ -200,5 +207,16 @@ export default function Home() {
)} )}
</div> </div>
</div> </div>
</Suspense>
); );
} }
const App = () => {
return (
<Suspense fallback={<div>Загрузка...</div>}>
<Home />
</Suspense>
);
};
export default App;
...@@ -27,7 +27,6 @@ const GameBoard: React.FC<GameBoardProps> = ({ ...@@ -27,7 +27,6 @@ const GameBoard: React.FC<GameBoardProps> = ({
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const cellSize = 60; const cellSize = 60;
const viewportSize = 800;
useEffect(() => { useEffect(() => {
if (containerRef.current) { if (containerRef.current) {
......
import React from 'react'; import React from 'react';
import {APP_URL} from '../../constants';
interface GameInviteProps { interface GameInviteProps {
roomId: string; roomId: string;
} }
const GameInvite: React.FC<GameInviteProps> = ({ roomId }) => { const GameInvite: React.FC<GameInviteProps> = ({ roomId }) => {
const gameUrl = typeof window !== 'undefined' ? `${window.location.origin}?room=${roomId}` : ''; const gameUrl = typeof window !== 'undefined' ? `${window.location.origin}${APP_URL}?room=${roomId}` : '';
const shareText = `Присоединяйся ко мне в игре!`; const shareText = `Присоединяйся ко мне в игре!`;
......
import { Server } from 'socket.io'; import { Server } from 'socket.io';
import { Server as NetServer } from 'http'; import { Server as NetServer } from 'http';
import { NextApiRequest } from 'next'; import { NextApiRequest, NextApiResponse } from 'next';
import { NextApiResponseWithSocket } from '../../types/next'; // import { NextApiResponseWithSocket } from '../../types/next';
import { GameState, GameMove } from '../../types/game'; import { GameState, GameMove, CellValue } from '../../types/game';
import {APP_URL} from '../../../constants';
export type NextApiResponseWithSocket = NextApiResponse & {
socket: {
server: NetServer & {
io: Server
}
}
}
const games = new Map<string, GameState>(); const games = new Map<string, GameState>();
...@@ -23,7 +34,7 @@ const createNewGame = (playerId: string): [string, GameState] => { ...@@ -23,7 +34,7 @@ const createNewGame = (playerId: string): [string, GameState] => {
isYourTurn: false, isYourTurn: false,
status: 'waiting', status: 'waiting',
turnTimeLimit: 20000, turnTimeLimit: 20000,
turnStartTime: null, turnStartTime: undefined,
players: { players: {
attacker: { attacker: {
id: playerId, id: playerId,
...@@ -54,44 +65,45 @@ const joinGame = (roomId: string, playerId: string): GameState | null => { ...@@ -54,44 +65,45 @@ const joinGame = (roomId: string, playerId: string): GameState | null => {
return game; return game;
}; };
const startNewRound = (game: GameState, firstReadyPlayerId: string): GameState => { // const startNewRound = (game: GameState, firstReadyPlayerId: string): GameState => {
// Определяем, кто будет атакующим в новой игре (тот, кто первый нажал "Играть снова") // // Определяем, кто будет атакующим в новой игре (тот, кто первый нажал "Играть снова")
const oldAttacker = game.players.attacker!; // const oldAttacker = game.players.attacker!;
const oldDefender = game.players.defender!; // const oldDefender = game.players.defender!;
// Определяем, кто первый нажал кнопку // // Определяем, кто первый нажал кнопку
const firstPlayer = firstReadyPlayerId === oldAttacker.id ? oldAttacker : oldDefender; // const firstPlayer = firstReadyPlayerId === oldAttacker.id ? oldAttacker : oldDefender;
const secondPlayer = firstReadyPlayerId === oldAttacker.id ? oldDefender : oldAttacker; // const secondPlayer = firstReadyPlayerId === oldAttacker.id ? oldDefender : oldAttacker;
// Сбрасываем состояние игры // // Сбрасываем состояние игры
const newGame: GameState = { // const newGame: GameState = {
...game, // ...game,
cells: {}, // cells: {},
currentPlayer: 'X', // currentPlayer: 'X',
winner: null, // winner: null,
status: 'playing', // status: 'playing',
lastMove: null, // lastMove: null,
turnStartTime: Date.now(), // turnStartTime: Date.now(),
readyForNewGame: {}, // readyForNewGame: {},
// Первый нажавший становится атакующим // // Первый нажавший становится атакующим
players: { // players: {
attacker: { // attacker: {
...firstPlayer, // ...firstPlayer,
isAttacker: true, // isAttacker: true,
nickname: 'Heker' // nickname: 'Heker'
}, // },
defender: { // defender: {
...secondPlayer, // ...secondPlayer,
isAttacker: false, // isAttacker: false,
nickname: 'Beluga' // nickname: 'Beluga'
} // }
} // }
}; // };
return newGame; // return newGame;
}; // };
const checkWinner = (cells: { [key: string]: string }, lastMove: GameMove): string | null => { const checkWinner = (cells: { [key: string]: CellValue } , lastMove: GameMove): CellValue => {
const directions = [ const directions = [
[0, 1], // horizontal [0, 1], // horizontal
[1, 0], // vertical [1, 0], // vertical
...@@ -126,15 +138,15 @@ const checkWinner = (cells: { [key: string]: string }, lastMove: GameMove): stri ...@@ -126,15 +138,15 @@ const checkWinner = (cells: { [key: string]: string }, lastMove: GameMove): stri
const handler = async (req: NextApiRequest, res: NextApiResponseWithSocket) => { const handler = async (req: NextApiRequest, res: NextApiResponseWithSocket) => {
if (!res.socket.server.io) { if (!res.socket.server.io) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const httpServer: NetServer = res.socket.server as any; const httpServer: NetServer = res.socket.server as any;
const io = new Server(httpServer, { const io = new Server(httpServer, {
path: '/api/socket', path: `${APP_URL}/api/socket`,
}); });
io.on('connection', (socket) => { io.on('connection', (socket) => {
console.log('Client connected:', socket.id); console.log('Client connected:', socket.id);
socket.on('createGame', () => {
socket.on('createGame', () => {
const [roomId, gameState] = createNewGame(socket.id); const [roomId, gameState] = createNewGame(socket.id);
socket.join(roomId); socket.join(roomId);
socket.emit('gameCreated', { roomId, gameState }); socket.emit('gameCreated', { roomId, gameState });
...@@ -174,7 +186,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponseWithSocket) => { ...@@ -174,7 +186,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponseWithSocket) => {
currentPlayer: 'X', currentPlayer: 'X',
winner: null, winner: null,
status: 'playing', status: 'playing',
lastMove: null, lastMove: undefined,
turnStartTime: Date.now() turnStartTime: Date.now()
}; };
...@@ -230,7 +242,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponseWithSocket) => { ...@@ -230,7 +242,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponseWithSocket) => {
game.cells[cellKey] = player; game.cells[cellKey] = player;
game.lastMove = { x, y, player }; game.lastMove = { x, y, player };
const winner = checkWinner(game.cells, { x, y, player }); const winner = checkWinner(game.cells, { x, y, player, roomId });
if (winner) { if (winner) {
game.winner = winner; game.winner = winner;
game.status = 'finished'; game.status = 'finished';
......
...@@ -43,7 +43,7 @@ export interface GameState { ...@@ -43,7 +43,7 @@ export interface GameState {
y: number; y: number;
player: 'X' | 'O'; player: 'X' | 'O';
}; };
turnStartTime?: number; turnStartTime?: number | undefined | null;
turnTimeLimit: number; // в миллисекундах turnTimeLimit: number; // в миллисекундах
readyForNewGame?: { readyForNewGame?: {
[playerId: string]: boolean; [playerId: string]: boolean;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment