Browse Source

Visual "Ready" functionality

master
Samplasion 3 years ago
parent
commit
ffb51f70f8
6 changed files with 94 additions and 27 deletions
  1. +37
    -0
      common/events.ts
  2. +3
    -1
      common/types.ts
  3. +1
    -1
      package.json
  4. +10
    -8
      server/index.ts
  5. +31
    -5
      server/routines/rooms.ts
  6. +12
    -12
      src/pages/waiting-for-players.tsx

+ 37
- 0
common/events.ts View File

@ -0,0 +1,37 @@
// Events received by the server
enum ClientEventNames {
CreateRoom = "createRoom",
JoinRoom = "joinRoom",
PlayersUpdate = "playersUpdate",
ExtractNumber = "extractNumber",
ChooseCartella = "chooseCartella",
UnchooseCartella = "unchooseCartella",
StartGame = "startGame",
ChoseAllCartelle = "choseAllCartelle",
PleaseGiveMeCartelle = "pleaseGiveMeCartelle",
GiveAllCartelle = "giveAllCartelle",
Ready = "ready"
}
// Events sent by the server
enum ServerEventNames {
CreateRoom = "createRoom",
HostClosed = "hostClosed",
JoinRoomError = "joinRoomError",
PlayersUpdate = "playersUpdate",
JoinRoom = "joinRoom",
ExtractedNumber = "extractedNumber",
Progress = "progress",
EndGame = "endGame",
ChosenCartella = "chosenCartella",
UnchosenCartella = "unchosenCartella",
EveryoneChose = "everyoneChose",
StartGameError = "startGameError",
StartingGame = "startingGame",
GaveMeCartelle = "gaveMeCartelle",
}
export {
ServerEventNames,
ClientEventNames
};

server/types.ts → common/types.ts View File

@ -11,10 +11,12 @@ export interface Player {
hasTabellone: boolean;
cartelle: number[];
choseAllCartelle: boolean;
ready: boolean;
}
export interface StrippedPlayer {
username: string;
id: SocketID;
ready: boolean;
}
export enum TombolaAction {
NONE,
@ -39,4 +41,4 @@ export interface Room {
export enum RoomJoinError {
NoSuchRoom,
GameHasStarted
}
};

+ 1
- 1
package.json View File

@ -93,7 +93,7 @@
"start": "craco start",
"build": "craco build",
"test": "craco test",
"server": "tsc --build server/tsconfig.json && node build_server"
"server": "tsc --build server/tsconfig.json && node build_server/server"
},
"eslintConfig": {
"extends": [


+ 10
- 8
server/index.ts View File

@ -6,33 +6,34 @@ import http from 'http';
import socketio from 'socket.io';
import randomstring from "randomstring";
// import routes from './routes';
import { chooseCartella, choseAllCartelle, createRoom, extractNumber, joinRoom, pleaseGiveMeCartelle, startGame, unchooseCartella, updatePlayers } from './routines/rooms';
import { chooseCartella, choseAllCartelle, createRoom, extractNumber, joinRoom, pleaseGiveMeCartelle, ready, startGame, unchooseCartella, updatePlayers } from './routines/rooms';
import cartelle from './cartelle';
import {
stripIndents
} from "common-tags";
import ip from "ip";
import { ClientEventNames } from "../common/events";
import { config } from "dotenv";
import { join } from 'path';
config({
path: join(__dirname, "..", ".env")
path: join(__dirname, "..", "..", ".env")
});
const app = express();
app.use(express.json());
app.use(express.urlencoded());
app.use(express.static(path.join(__dirname, '..', 'build')));
app.use(express.static(path.join(__dirname, '..', '..', 'build')));
// app.use(routes);
// 404 route
app.get("*", (req, res) => res.sendFile(path.join(__dirname, '..', 'build', 'index.html')));
app.get("*", (req, res) => res.sendFile(path.join(__dirname, '..', '..', 'build', 'index.html')));
const server = http.createServer(app);
const io = new socketio.Server(server, {
cors: {
origin: "http://localhost:8080",
origin: process.env.DOMAIN,
methods: ["GET", "POST"]
}
});
@ -50,10 +51,11 @@ io.on("connection", (socket: socketio.Socket) => {
socket.on("unchooseCartella", unchooseCartella.bind(null, socket, ID));
socket.on("startGame", startGame.bind(null, socket, ID));
socket.on("choseAllCartelle", choseAllCartelle.bind(null, socket, ID));
socket.on("pleaseGiveMeCartelle", pleaseGiveMeCartelle.bind(null, socket, ID));
socket.on("giveAllCartelle", () => {
socket.emit("giveAllCartelle", cartelle);
socket.on(ClientEventNames.PleaseGiveMeCartelle, pleaseGiveMeCartelle.bind(null, socket, ID));
socket.on(ClientEventNames.GiveAllCartelle, () => {
socket.emit(ClientEventNames.GiveAllCartelle, cartelle);
});
socket.on(ClientEventNames.Ready, ready.bind(null, socket, ID));
})
const PORT = process.env.PORT || 8080;


+ 31
- 5
server/routines/rooms.ts View File

@ -1,7 +1,8 @@
import { Socket } from "socket.io";
import randomstring from "randomstring";
import { PracticalTombolaAction, Room, RoomJoinError, SocketID, SocketWrapper, TombolaAction } from "../types";
import { PracticalTombolaAction, Room, RoomJoinError, SocketID, SocketWrapper, StrippedPlayer, TombolaAction } from "../../common/types";
import cartelle from "../cartelle";
import { ServerEventNames } from "../../common/events";
const rooms = new Map<string, Room>();
const flatbellone = [...Array(90).keys()].map(n => n + 1);
@ -29,6 +30,7 @@ export function createRoom(socket: Socket, id: SocketID, username: string) {
hasTabellone: false,
cartelle: [],
choseAllCartelle: false,
ready: true,
}
],
gameStarted: false,
@ -71,7 +73,8 @@ export function joinRoom(socket: Socket, id: SocketID, username: string, roomID:
username,
hasTabellone: false,
cartelle: [],
choseAllCartelle: false
choseAllCartelle: false,
ready: false,
});
room.players.forEach(player => {
@ -100,10 +103,12 @@ export function joinRoom(socket: Socket, id: SocketID, username: string, roomID:
export function updatePlayers(socket: Socket, id: SocketID, roomID: string) {
if (!rooms.has(roomID))
return socket.emit("playersUpdate", []);
socket.emit("playersUpdate", rooms.get(roomID)!.players.map(player => {
const room = rooms.get(roomID)!;
socket.emit("playersUpdate", room.players.map((player): StrippedPlayer => {
return {
id: player.socketData.id,
name: player.username
username: player.username,
ready: player.ready
}
}));
}
@ -136,7 +141,8 @@ export function extractNumber(socket: Socket, id: SocketID) {
room.winners[previousOne(room.nextProgress) as PracticalTombolaAction] = progressing.map(({ player }) => {
return {
username: player.username,
id: player.socketData.id
id: player.socketData.id,
ready: player.ready
}
});
}
@ -259,6 +265,26 @@ export function pleaseGiveMeCartelle(socket: Socket, id: SocketID) {
socket.emit("gaveMeCartelle", room.players.find(player => player.socketData.id == id)?.cartelle ?? [0]);
}
export function ready(socket: Socket, id: SocketID) {
const roomID = roomIDForID(id) ?? "";
const room = rooms.get(roomID);
if (!room)
return;
const i = room.players.findIndex(p => p.socketData.id === id);
room.players[i].ready = !room.players[i].ready;
everySocket(id).forEach(socket => {
socket.emit(ServerEventNames.PlayersUpdate, room.players.map((p): StrippedPlayer => {
return {
id: p.socketData.id,
username: p.username,
ready: p.ready
}
}))
});
}
function roomIDForID(id: SocketID): string | undefined {
return [...rooms.entries()].find(([k, v]) => {
return v.players.map(s => s.socketData.id).includes(id);


+ 12
- 12
src/pages/waiting-for-players.tsx View File

@ -3,6 +3,7 @@ import React from "react";
import Heading from "../components/Heading";
import { useHistory } from "react-router-dom";
import Modal from "../components/Modal";
import { StrippedPlayer } from "../../common/types";
interface WaitingForPlayersProps {
socket: Socket;
@ -10,13 +11,9 @@ interface WaitingForPlayersProps {
gameKey: string;
host: boolean;
}
interface Player {
id: string;
name: string;
}
export const WaitingForPlayers: React.FunctionComponent<WaitingForPlayersProps> = ({ socket, socketID, gameKey, host }) => {
const [players, setPlayers] = React.useState<Player[]>([]);
const [players, setPlayers] = React.useState<StrippedPlayer[]>([]);
const [open, setOpen] = React.useState(false);
const history = useHistory();
@ -27,7 +24,7 @@ export const WaitingForPlayers: React.FunctionComponent<WaitingForPlayersProps>
// Request a player update
console.log(gameKey);
socket.emit("playersUpdate", gameKey);
socket.on("playersUpdate", (players: Player[]) => setPlayers(players));
socket.on("playersUpdate", (players: StrippedPlayer[]) => setPlayers(players));
socket.on("startingGame", (givesTabellone: boolean) => {
history.push(givesTabellone ? "/tabellone" : "/choose-cartelle");
});
@ -43,7 +40,7 @@ export const WaitingForPlayers: React.FunctionComponent<WaitingForPlayersProps>
<Heading
className={host ? "w-full md:w-1/2" : ""}
title="Aspettando gli altri giocatori..."
subtitle={host ? 'Quando sei pronto, premi "Gioca".' : "L'host della partita sceglierà quando iniziare."}
subtitle={host ? 'Quando siete tutti pronti, premi "Gioca".' : 'Clicca "Pronto" per indicare all\'host che sei pronto per giocare.'}
/>
{host && (
<div className="w-full md:w-1/2">
@ -53,14 +50,17 @@ export const WaitingForPlayers: React.FunctionComponent<WaitingForPlayersProps>
</div>
<ol className="list-decimal my-4 pl-10">
{players.map(p => {
return <li>{p.name} {p.id === socketID && <>(<b>Tu!</b>)</>}</li>
return <li><span className={p.ready ? "text-green-700 dark:text-green-400" : ""}>{p.username}</span> {p.id === socketID && <>(<b>Tu!</b>)</>}</li>
})}
</ol>
{host && (
<div className="flex justify-end">
<div className="flex justify-end">
{host && (
<button className="btn my-4 s-full md:ws-auto" onClick={() => socket.emit("startGame")}>Gioca</button>
</div>
)}
)}
<button style={{ marginTop: "1rem" }} className={"btn my-4 s-full mt-4" + (host ? " btn-outline" : "")} onClick={() => socket.emit("ready")}>
{players.find(player => player.id === socketID)?.ready ? "Non pronto" : "Pronto"}
</button>
</div>
<Modal
title="Attenzione"
open={open}


Loading…
Cancel
Save