From fbcb48f9ad29fe1b4eb17ed28ee8a236ae3d3de1 Mon Sep 17 00:00:00 2001 From: gparant Date: Sat, 4 Apr 2020 19:25:08 +0200 Subject: [PATCH] Share players position using Socket.IO - I stocked information user (id, room and position) in socket client. - I created function to send all information every few 10 milliseconds. Note : when the front will be available, we must check the performance of back server. --- back/src/Controller/AuthenticateController.ts | 4 +- back/src/Controller/IoSocketController.ts | 67 +++++++++++++++++-- back/src/Enum/EnvironmentVariable.ts | 4 +- back/src/Model/Websocket/ExSocketInterface.ts | 4 +- 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/back/src/Controller/AuthenticateController.ts b/back/src/Controller/AuthenticateController.ts index 01985b6a..c810ea8a 100644 --- a/back/src/Controller/AuthenticateController.ts +++ b/back/src/Controller/AuthenticateController.ts @@ -1,7 +1,7 @@ import {Application, Request, Response} from "express"; import Jwt, {JsonWebTokenError} from "jsonwebtoken"; import {BAD_REQUEST, OK} from "http-status-codes"; -import {SECRET_KEY} from "../Enum/EnvironmentVariable"; +import {SECRET_KEY, ROOM} from "../Enum/EnvironmentVariable"; export class AuthenticateController{ App : Application; @@ -21,7 +21,7 @@ export class AuthenticateController{ }); } //TODO check user email for The Coding Machine game - let token = Jwt.sign({email: param.email}, SECRET_KEY, {expiresIn: '24h'}); + let token = Jwt.sign({email: param.email, roomId: ROOM}, SECRET_KEY, {expiresIn: '24h'}); return res.status(OK).send({token: token}); }); } diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index 5dbacdac..696f3267 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -26,6 +26,7 @@ export class IoSocketController{ }); this.ioConnection(); + this.shareUsersPosition(); } ioConnection() { @@ -38,7 +39,6 @@ export class IoSocketController{ x: user x position on map y: user y position on map */ - socket.on('join-room', (message : string) => { let messageUserPosition = this.hydrateMessageReceive(message); if(messageUserPosition instanceof Error){ @@ -47,7 +47,7 @@ export class IoSocketController{ //join user in room socket.join(messageUserPosition.roomId); // sending to all clients in room except sender - this.saveUserPosition((socket as ExSocketInterface), messageUserPosition); + this.saveUserInformation((socket as ExSocketInterface), messageUserPosition); socket.to(messageUserPosition.roomId).emit('join-room', messageUserPosition.toString()); }); @@ -57,15 +57,17 @@ export class IoSocketController{ return socket.emit("message-error", JSON.stringify({message: messageUserPosition.message})); } // sending to all clients in room except sender - this.saveUserPosition((socket as ExSocketInterface), messageUserPosition); + this.saveUserInformation((socket as ExSocketInterface), messageUserPosition); socket.to(messageUserPosition.roomId).emit('join-room', messageUserPosition.toString()); }); }); } //permit to save user position in socket - saveUserPosition(socket : ExSocketInterface, message : MessageUserPosition){ + saveUserInformation(socket : ExSocketInterface, message : MessageUserPosition){ socket.position = message.position; + socket.roomId = message.roomId; + socket.userId = message.userId; } //Hydrate and manage error @@ -77,4 +79,61 @@ export class IoSocketController{ return new Error(err); } } + + /** permit to share user position + ** users position will send in event 'user-position' + ** The data sent is an array with information for each user : + [ + { + userId: , + roomId: , + position: { + x : , + y : + } + }, + ... + ] + **/ + seTimeOutInProgress : any = null; + shareUsersPosition(){ + if(!this.seTimeOutInProgress) { + clearTimeout(this.seTimeOutInProgress); + } + let clients = this.Io.clients(); + let socketsKey = Object.keys(this.Io.clients().sockets); + + //create mapping with all users in all rooms + let mapPositionUserByRoom = new Map(); + for(let i = 0; i < socketsKey.length; i++){ + let socket = clients.sockets[socketsKey[i]]; + if(!(socket as ExSocketInterface).position){ + continue; + } + let data = { + userId : (socket as ExSocketInterface).userId, + roomId : (socket as ExSocketInterface).roomId, + position : (socket as ExSocketInterface).position, + }; + let dataArray = []; + if(mapPositionUserByRoom.get(data.roomId)){ + dataArray = mapPositionUserByRoom.get(data.roomId); + dataArray.push(data); + }else{ + dataArray = [data]; + } + mapPositionUserByRoom.set(data.roomId, dataArray); + } + + //send for each room, all data of position user + let arrayMap = Array.from(mapPositionUserByRoom); + arrayMap.forEach((value) => { + let roomId = value[0]; + let data = value[1]; + this.Io.in(roomId).emit('user-position', JSON.stringify(data)); + }); + this.seTimeOutInProgress = setTimeout(() => { + this.shareUsersPosition(); + }, 10); + } } \ No newline at end of file diff --git a/back/src/Enum/EnvironmentVariable.ts b/back/src/Enum/EnvironmentVariable.ts index 27f56d78..f795bf90 100644 --- a/back/src/Enum/EnvironmentVariable.ts +++ b/back/src/Enum/EnvironmentVariable.ts @@ -1,5 +1,7 @@ const SECRET_KEY = process.env.SECRET_KEY || "THECODINGMACHINE_SECRET_KEY"; +const ROOM = process.env.ROOM || "THECODINGMACHINE"; export { - SECRET_KEY + SECRET_KEY, + ROOM } \ No newline at end of file diff --git a/back/src/Model/Websocket/ExSocketInterface.ts b/back/src/Model/Websocket/ExSocketInterface.ts index 51df9258..095d3cbc 100644 --- a/back/src/Model/Websocket/ExSocketInterface.ts +++ b/back/src/Model/Websocket/ExSocketInterface.ts @@ -2,6 +2,8 @@ import {Socket} from "socket.io"; import {PointInterface} from "./PointInterface"; export interface ExSocketInterface extends Socket { - token: object; + token: any; + roomId: string; + userId: string; position: PointInterface; } \ No newline at end of file