diff --git a/.hmrc b/.hmrc
index d4489dd..ccf8ad9 100644
--- a/.hmrc
+++ b/.hmrc
@@ -2,7 +2,7 @@
"path": "G:\\Other\\Development\\Projects\\[ideas]\\domino",
"name": "domino-server",
"initialVersion": "0.1.1",
- "version": "0.1.4",
+ "version": "0.1.5",
"docker": {
"useRegistry": true,
"registry": "192.168.1.115:5000",
@@ -75,7 +75,7 @@
},
"_backup": {
"name": "domino-server",
- "version": "0.1.3",
+ "version": "0.1.4",
"description": "",
"main": "index.js",
"engines": {
@@ -88,8 +88,8 @@
"test": "node --env-file=.env -r ts-node/register src/test.ts",
"test:watch": "node --env-file=.env --watch -r ts-node/register src/test.ts",
"docker-build": "docker build -t 192.168.1.115:5000/arhuako/domino-server:latest .",
- "docker-tag": "docker tag 192.168.1.115:5000/arhuako/domino-server:latest 192.168.1.115:5000/arhuako/domino-server:0.1.3",
- "docker-push": "docker push 192.168.1.115:5000/arhuako/domino-server:latest && docker push 192.168.1.115:5000/arhuako/domino-server:0.1.3",
+ "docker-tag": "docker tag 192.168.1.115:5000/arhuako/domino-server:latest 192.168.1.115:5000/arhuako/domino-server:0.1.4",
+ "docker-push": "docker push 192.168.1.115:5000/arhuako/domino-server:latest && docker push 192.168.1.115:5000/arhuako/domino-server:0.1.4",
"publish": "npm run docker-build && npm run docker-tag && npm run docker-push"
},
"keywords": [],
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c1b0e7f..2d6c944 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file.
## Unreleased
+## 0.1.5 - 2024-07-24
+### Added
+- socket.io room management
+
## 0.1.4 - 2024-07-20
## 0.1.3 - 2024-07-18
diff --git a/package.json b/package.json
index 1961a19..7f4fea9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "domino-server",
- "version": "0.1.4",
+ "version": "0.1.5",
"description": "",
"main": "index.js",
"engines": {
@@ -13,8 +13,8 @@
"test": "node --env-file=.env -r ts-node/register src/test.ts",
"test:watch": "node --env-file=.env --watch -r ts-node/register src/test.ts",
"docker-build": "docker build -t 192.168.1.115:5000/arhuako/domino-server:latest .",
- "docker-tag": "docker tag 192.168.1.115:5000/arhuako/domino-server:latest 192.168.1.115:5000/arhuako/domino-server:0.1.4",
- "docker-push": "docker push 192.168.1.115:5000/arhuako/domino-server:latest && docker push 192.168.1.115:5000/arhuako/domino-server:0.1.4",
+ "docker-tag": "docker tag 192.168.1.115:5000/arhuako/domino-server:latest 192.168.1.115:5000/arhuako/domino-server:0.1.5",
+ "docker-push": "docker push 192.168.1.115:5000/arhuako/domino-server:latest && docker push 192.168.1.115:5000/arhuako/domino-server:0.1.5",
"publish": "npm run docker-build && npm run docker-tag && npm run docker-push"
},
"keywords": [],
diff --git a/public/CHANGELOG.html b/public/CHANGELOG.html
index c69d4d3..a956f19 100644
--- a/public/CHANGELOG.html
+++ b/public/CHANGELOG.html
@@ -1,5 +1,10 @@
Changelog
All notable changes to this project will be documented in this file.
+0.1.5 - 2024-07-24
+Added
+
+- socket.io room management
+
0.1.4 - 2024-07-20
0.1.3 - 2024-07-18
Added
diff --git a/src/game/DominoesGame.ts b/src/game/DominoesGame.ts
index 76592a8..f409f72 100644
--- a/src/game/DominoesGame.ts
+++ b/src/game/DominoesGame.ts
@@ -144,7 +144,7 @@ export class DominoesGame extends EventEmitter {
playTurn() {
try {
const player = this.players[this.currentPlayerIndex];
- this.notificationService.sendEventToPlayers('server:next-turn', this.players, this.getGameState());
+ this.notificationService.sendEventToPlayers('server:next-turn', this.players, this.getState());
this.logger.debug(`${player.name}'s turn (${player.hand.length} tiles)`);
this.printPlayerHand(player);
printBoard(this.board)
@@ -222,6 +222,7 @@ export class DominoesGame extends EventEmitter {
players: this.players.map(player => player.getState(true)),
board: this.board.tiles.map(tile => tile.getState(true)),
boneyard: this.board.boneyard.map(tile => tile.getState(true)),
+ movements: this.board.movements
}
this.emit('game-over', summary);
}
@@ -264,7 +265,7 @@ export class DominoesGame extends EventEmitter {
this.deal();
const extractStates = (p: PlayerInterface) => ({
player: p.getState(true),
- gameState: this.getGameState()
+ gameState: this.getState()
});
await this.notificationService.sendEventToPlayers('server:hand-dealt', this.players, extractStates);
@@ -325,11 +326,14 @@ export class DominoesGame extends EventEmitter {
}
}
- getGameState(): GameState {
+ getState(): GameState {
const currentPlayer = this.players[this.currentPlayerIndex]
+ const lastMove = this.lastMove?.getState() || null;
+ const movements = this.board.movements.map(move => move.getState());
+
return {
id: uuid(),
- lastMove: this.lastMove,
+ lastMove,
gameInProgress: this.gameInProgress,
winner: this.winner,
tileSelectionPhase: this.tileSelectionPhase,
@@ -337,10 +341,11 @@ export class DominoesGame extends EventEmitter {
gameTied: this.gameTied,
gameId: this.id,
boneyard: this.board.boneyard.map(tile => tile.getState(false)),
- players: this.players.map(player => player.getState()),
+ players: this.players.map(player => player.getState(false)),
currentPlayer: currentPlayer.getState(),
board: this.board.tiles.map(tile => tile.getState(true)),
boardFreeEnds: this.board.getFreeEnds(),
+ movements
}
}
diff --git a/src/game/MatchSession.ts b/src/game/MatchSession.ts
index 2f98894..c004ae6 100644
--- a/src/game/MatchSession.ts
+++ b/src/game/MatchSession.ts
@@ -26,6 +26,7 @@ export class MatchSession {
private clientsReady: string[] = [];
private gameSummaries: GameSummary[] = [];
private sessionService: SessionService = new SessionService();
+ private room: string;
id: string;
matchInProgress: boolean = false;
@@ -46,6 +47,7 @@ export class MatchSession {
const { sessionName, seed, winType, winTarget } = options;
this.seed = seed || getRandomSeed();
this.id = uuid();
+ this.room = `room-${this.id}`;
this.name = sessionName || `Match ${this.id}`;
this.addPlayerToSession(creator);
this.creator = creator;
@@ -187,7 +189,6 @@ export class MatchSession {
});
} else {
this.status = 'waiting'
- // await this.playerNotificationManager.notifyMatchState(this);
this.notificationService.sendEventToPlayers('server:game-finished', this.players, {
lastGame: gameSummary,
sessionState: this.getState(true)
@@ -397,6 +398,7 @@ export class MatchSession {
matchInProgress: this.matchInProgress,
gameSummaries: this.gameSummaries,
options: this.options,
+ room: this.room,
};
}
diff --git a/src/game/dto/GameState.ts b/src/game/dto/GameState.ts
index fda4a26..5b46892 100644
--- a/src/game/dto/GameState.ts
+++ b/src/game/dto/GameState.ts
@@ -1,5 +1,4 @@
-import { PlayerMove } from "../entities/PlayerMove";
-import { PlayerDto } from "./PlayerDto";
+import { PlayerDto, PlayerMoveDto } from "./PlayerDto";
export interface GameState {
id: string;
@@ -14,5 +13,6 @@ export interface GameState {
gameId: string;
tileSelectionPhase: boolean;
boardFreeEnds: number[];
- lastMove: PlayerMove | null;
+ lastMove: PlayerMoveDto | null;
+ movements: PlayerMoveDto[];
}
\ No newline at end of file
diff --git a/src/game/dto/GameSummary.ts b/src/game/dto/GameSummary.ts
index 8e7c571..a79a07e 100644
--- a/src/game/dto/GameSummary.ts
+++ b/src/game/dto/GameSummary.ts
@@ -1,4 +1,5 @@
import { Score } from "../../server/db/interfaces";
+import { PlayerMove } from "../entities/PlayerMove";
import { PlayerDto, TileDto } from "./PlayerDto";
export interface GameSummary {
@@ -10,4 +11,5 @@ export interface GameSummary {
players?: PlayerDto[];
board: TileDto[]
boneyard: TileDto[]
+ movements: PlayerMove[]
}
\ No newline at end of file
diff --git a/src/game/dto/MatchSessionOptions.ts b/src/game/dto/MatchSessionOptions.ts
index 84e62ee..78018c2 100644
--- a/src/game/dto/MatchSessionOptions.ts
+++ b/src/game/dto/MatchSessionOptions.ts
@@ -10,4 +10,5 @@ export interface MatchSessionOptions {
seed: string
sessionName: string
numPlayers: 1 | 2 | 3 | 4
+ turnWaitSeconds: number
}
\ No newline at end of file
diff --git a/src/game/dto/MatchSessionState.ts b/src/game/dto/MatchSessionState.ts
index 437ab8c..3d662bd 100644
--- a/src/game/dto/MatchSessionState.ts
+++ b/src/game/dto/MatchSessionState.ts
@@ -1,4 +1,5 @@
import { Score } from "../../server/db/interfaces";
+import { GameState } from "./GameState";
import { GameSummary } from "./GameSummary";
import { MatchSessionOptions } from "./MatchSessionOptions";
import { PlayerDto } from "./PlayerDto";
@@ -22,4 +23,6 @@ export interface MatchSessionState {
playersReady: number,
gameSummaries: GameSummary[];
options: MatchSessionOptions
+ currentGame?: GameState
+ room: string
}
\ No newline at end of file
diff --git a/src/game/dto/PlayerDto.ts b/src/game/dto/PlayerDto.ts
index 4de00e7..844af97 100644
--- a/src/game/dto/PlayerDto.ts
+++ b/src/game/dto/PlayerDto.ts
@@ -14,4 +14,12 @@ export interface PlayerDto {
teamedWith?: string;
ready: boolean;
isHuman: boolean;
+}
+
+export interface PlayerMoveDto {
+ id: string;
+ tile: TileDto
+ type: string | null;
+ playerId: string;
+ direction?: string;
}
\ No newline at end of file
diff --git a/src/game/entities/Board.ts b/src/game/entities/Board.ts
index 7d60a41..164317f 100644
--- a/src/game/entities/Board.ts
+++ b/src/game/entities/Board.ts
@@ -9,6 +9,7 @@ export class Board {
tiles: Tile[] = [];
boneyard: Tile[] = [];
logger = new LoggingService();
+ movements: PlayerMove[] = [];
constructor(private rng: PRNG) {}
@@ -64,6 +65,7 @@ export class Board {
this.playTileRight(tile);
// printLine(`${tile} -- right`);
}
+ this.movements.push(playerMove);
}
playTileLeft(tile: Tile) {
diff --git a/src/game/entities/PlayerMove.ts b/src/game/entities/PlayerMove.ts
index 3f60d02..ee10dfe 100644
--- a/src/game/entities/PlayerMove.ts
+++ b/src/game/entities/PlayerMove.ts
@@ -1,5 +1,6 @@
import { uuid } from "../../common/utilities";
import { PlayerMoveSideType } from "../constants";
+import { PlayerMoveDto } from "../dto/PlayerDto";
import { Tile } from "./Tile";
export class PlayerMove {
@@ -9,4 +10,14 @@ export class PlayerMove {
toString() {
return `PlayerMove:([${this.tile.pips[0]}|${this.tile.pips[1]}] ${this.type})`;
}
+
+ getState(): PlayerMoveDto {
+ return {
+ id: this.id,
+ tile: this.tile.getState(),
+ type: this.type,
+ playerId: this.playerId,
+ direction: this.direction,
+ };
+ }
}
\ No newline at end of file
diff --git a/src/server/controllers/AuthController.ts b/src/server/controllers/AuthController.ts
index a5cecc1..b63bbb7 100644
--- a/src/server/controllers/AuthController.ts
+++ b/src/server/controllers/AuthController.ts
@@ -6,49 +6,72 @@ import { TemporalTokenMongoManager } from '../db/mongo/TemporalTokenMongoManager
import { BaseController } from './BaseController';
import { NextFunction, Request, Response } from 'express';
import { AuthenticationOption, Token, User } from '../db/interfaces';
+import { UserSessionMongoManager } from '../db/mongo/UserSessionMongoManager';
export class AuthController extends BaseController {
security = new SecurityManager();
usersManager = new UsersMongoManager();
temporalTokenManager = new TemporalTokenMongoManager();
+ userSessionManager = new UserSessionMongoManager();
async login(req: Request, res: Response): Promise {
const { log } = req;
try {
- let token = null
const { username, password } = req.body;
- this.logger.debug('login', username, password);
const { valid: isValidPassword, user } = await this._checkPassword(username, password);
- this.logger.debug('isValidPassword', isValidPassword);
- if (!isValidPassword) {
+ if (!isValidPassword || user === null) {
res.status(401).json({ error: 'Unauthorized' }).end();
log.error('Unauthorized login attempt for user: ', username);
return;
}
- this._jwtSignUser(user, res)
+ delete user.hash;
+ let sessionId = await this.userSessionManager.renewSession(user.id);
+ const token = await this.security.signJwt({ sessionId, user}, false);
+ if (token === null) {
+ res.status(401).json({ error: 'Unauthorized' }).end();
+ return;
+ }
+ const refreshToken = await this.security.signJwt({ sessionId, user}, true);
+ res.status(200).json({ token, refreshToken }).end();
} catch (error) {
this.handleError(res, error);
}
}
async refresh(req: Request, res: Response): Promise {
- const { log } = req;
try {
- const { token } = req.body;
- const user = await this.security.verifyJwt(token);
- this._jwtSignUser(user, res, true);
+ const { refreshToken } = req.body;
+ if (!refreshToken) {
+ res.status(401).json({ error: 'Unauthorized' }).end();
+ return;
+ }
+ const data = await this.security.verifyJwt(refreshToken);
+ const { uuid: sessionId } = await this.userSessionManager.getByUuid(data.sessionId) || { uuid: undefined };
+ if (!data.sessionId || !data.user || data.sessionId !== sessionId) {
+ res.status(401).json({ error: 'Unauthorized' }).end();
+ return;
+ }
+ const newToken = await this.security.signJwt(data, false);
+ res.status(200).json({ token: newToken }).end();
} catch (error) {
- this.handleError(res, error);
+ res.status(401).json({ error: 'Unauthorized' }).end();
}
}
- _jwtSignUser(user: User | null, res: Response, isRefresh: boolean = false) {
+ async _jwtSignUser(user: User | null, res: Response, isFromRefresh: boolean = false) {
if (user === null) {
res.status(401).json({ error: 'Unauthorized' }).end();
return;
}
delete user.hash;
- const token = this.security.signJwt(user, false);
+ let uuid;
+ if (!isFromRefresh) {
+ uuid = await this.userSessionManager.renewSession(user.id);
+ } else {
+ const userSession = await this.userSessionManager.getUserSession(user.id);
+ uuid = userSession?.uuid;
+ }
+ const token = this.security.signJwt({ sessionId: uuid, user}, false);
if (token === null) {
res.status(401).json({ error: 'Unauthorized' }).end();
} else {
@@ -56,8 +79,8 @@ export class AuthController extends BaseController {
token: string,
refreshToken?: string
} = { token };
- if (!isRefresh) {
- data.refreshToken = this.security.signJwt(user, true);
+ if (!isFromRefresh) {
+ data.refreshToken = this.security.signJwt({ sessionId: uuid, user}, true);
}
res.status(200).json(data).end();
}
@@ -177,21 +200,27 @@ export class AuthController extends BaseController {
static authenticate(options: AuthenticationOption = {}) {
return async function(req: Request, res: Response, next: NextFunction) {
const security = new SecurityManager();
+ const userSessionManager = new UserSessionMongoManager();
const token = req.headers.authorization;
const { roles = [] } = options;
if (!token) {
return res.status(401).json({ error: 'Unauthorized' });
}
try {
- const user: User = await security.verifyJwt(token);
+ const parsed = await security.verifyJwt(token);
+ const user: User = parsed.user;
+ const userSession = await userSessionManager.getUserSession(user.id);
const validRoles = await AuthController.checkRoles(user, roles);
if (!validRoles) {
return res.status(403).json({ error: 'Forbidden' });
}
+ if (userSession?.uuid !== parsed.sessionId) {
+ return res.status(401).json({ error: 'Unauthorized' });
+ }
req.user = user;
next();
} catch (error) {
- return res.status(401).json({ error: 'Unauthorized' });
+ return res.status(401).json({ error: 'Token expired' });
}
}
}
diff --git a/src/server/controllers/UpdaterController.ts b/src/server/controllers/UpdaterController.ts
index 9735388..d144ef2 100644
--- a/src/server/controllers/UpdaterController.ts
+++ b/src/server/controllers/UpdaterController.ts
@@ -2,13 +2,13 @@ import { Request, Response } from "express";
import { BaseController } from "./BaseController";
const json = {
- "version": "0.1.10",
- "notes": "ADDEDD\n======\n- Updater\n- Refresh authentication when expires\n- Match summary page phase 1",
+ "version": "0.1.12",
+ "notes": "- v0.1.12\nAdded: I18n translations\nAdded: Win conditions\nFixed: Multiplayer join button not accessible\n- v0.1.8\nAdded: Updater\nAdded: Refresh authentication when expires\nAdded: Match summary page phase 1",
"pub_date": "2024-07-20T10:25:57Z",
"platforms": {
"windows-x86_64": {
- "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVTdDh5VEM1Y1hnUUF0N0lJVEl0SDM0QnAvRCs0OXpzMUhyQ3A3UHNxbUsrSWFMOWFDTkJqVVZBRXdNWmR3ME5hUU8wUEh4ajhaUktoZGEycFhoaFpwTno2WlZBRlhaRHdrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzIxNDgwMDM3CWZpbGU6ZG9taW5vLWNsaWVudF8wLjEuMTBfeDY0LXNldHVwLm5zaXMuemlwCk0rTDNUR3N6WHY5VnRRQU9hRnVFQnQybStFcndYRDRQY0hQNng1eFFDKzFvVngzaXhOaGZRRjBndkhxYXQxUkNrT1RNcHo2enM0VXh0eUJITHlveENnPT0K",
- "url": "https://test.xintanalabs.net/updates/domino-client_0.1.10_x64-setup.nsis.zip"
+ "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVTdDh5VEM1Y1hnUUVXbkxjSWVCTHE1cGhmd291QWFaODdFTGJINlhHNzhkU0lOZjRETERYZFZsUkpySmZONXpSdnBvMHFjOFd6UEpFVGxyRjNPRlpRVGkvTytqeU9KK1FnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzIxNjY1NTU5CWZpbGU6ZG9taW5vLWNsaWVudF8wLjEuMTJfeDY0LXNldHVwLm5zaXMuemlwClcxVXJOMmx2T3pGUlpqUTJXTWpNeHAveGR5ZkUxQVFQOVc4MjhuQVVJSkJ2bUw0eS8vZWtwR0dmWWhkd2t5RGNCVGQ5V09ORGp0VENUTGFBbkFBK0J3PT0K",
+ "url": "https://domserv.xintanalabs.net/updates/domino-client_0.1.12_x64-setup.nsis.zip"
}
}
}
@@ -18,7 +18,7 @@ export class UpdaterController extends BaseController {
this.logger.info('Checking for updates');
return res.json(json).status(200).end();
- return res.status(204).end();
+ // return res.status(204).end();
}
// async startMatchSession(data: any): Promise {
diff --git a/src/server/db/DbAdapter.ts b/src/server/db/DbAdapter.ts
index 0adcd24..182bb76 100644
--- a/src/server/db/DbAdapter.ts
+++ b/src/server/db/DbAdapter.ts
@@ -18,6 +18,7 @@ export function matchSessionAdapter(session: MatchSession, showPips: boolean = f
status: state.status,
matchInProgress: state.matchInProgress,
gameSummaries: state.gameSummaries,
+ room: state.room
}
}
\ No newline at end of file
diff --git a/src/server/db/interfaces.ts b/src/server/db/interfaces.ts
index a4ad7c6..b1557eb 100644
--- a/src/server/db/interfaces.ts
+++ b/src/server/db/interfaces.ts
@@ -61,6 +61,7 @@ export interface DbMatchSession extends EntityMongo {
status: string;
matchInProgress: boolean;
gameSummaries: GameSummary[];
+ room: string;
}
export interface DbUser extends EntityMongo {
@@ -115,4 +116,9 @@ export interface DbListResponse{
}
sort?: any;
data: EntityMongo[];
+}
+
+export interface UserSession extends EntityMongo {
+ userId: string;
+ uuid: string;
}
\ No newline at end of file
diff --git a/src/server/db/mongo/UserSessionMongoManager.ts b/src/server/db/mongo/UserSessionMongoManager.ts
new file mode 100644
index 0000000..7992041
--- /dev/null
+++ b/src/server/db/mongo/UserSessionMongoManager.ts
@@ -0,0 +1,37 @@
+import { uuid } from "../../../common/utilities";
+import { UserSession } from "../interfaces";
+import { BaseMongoManager } from "./common/BaseMongoManager";
+
+export class UserSessionMongoManager extends BaseMongoManager {
+ collection = 'userSessions';
+ constructor() {
+ super();
+ }
+
+ async createSession(userId: string): Promise {
+ const uid: string = uuid();
+ const userSession: UserSession = {
+ userId,
+ uuid: uid
+ }
+ await this.create(userSession);
+ return uid;
+ }
+
+ async removeSession(userId: string): Promise {
+ return this.deleteByFilter({ userId });
+ }
+
+ async renewSession(userId: string): Promise {
+ await this.removeSession(userId);
+ return this.createSession(userId);
+ }
+
+ async getUserSession(userId: string): Promise {
+ return this.getByFilter({ userId }) as Promise;
+ }
+
+ async getByUuid(uuid: string): Promise {
+ return this.getByFilter({ uuid }) as Promise;
+ }
+}
diff --git a/src/server/managers/SecurityManager.ts b/src/server/managers/SecurityManager.ts
index 83b1ecb..22dcaf3 100644
--- a/src/server/managers/SecurityManager.ts
+++ b/src/server/managers/SecurityManager.ts
@@ -29,13 +29,13 @@ export class SecurityManager extends ManagerBase {
}
// TODO: verificar esto
- async verifyJwt(token: string): Promise {
+ async verifyJwt(token: string): Promise {
return new Promise((resolve, reject) => {
jwt.verify(token, this.jwtSecretKey, (err, decoded) => {
if (err) {
reject(err);
} else {
- resolve(decoded as User);
+ resolve(decoded);
}
});
});
diff --git a/src/server/services/InteractionService.ts b/src/server/services/InteractionService.ts
index 9be5bb0..3277fef 100644
--- a/src/server/services/InteractionService.ts
+++ b/src/server/services/InteractionService.ts
@@ -97,7 +97,6 @@ export class InteractionService extends ServiceBase{
};
}
}
-
private onPlayerReady(data: any): any {
const { userId, sessionId } = data;
const session: MatchSession | undefined = this.sessionManager.getSession(sessionId);
diff --git a/src/server/services/PlayerNotificationService.ts b/src/server/services/PlayerNotificationService.ts
index 643a5a7..71edf76 100644
--- a/src/server/services/PlayerNotificationService.ts
+++ b/src/server/services/PlayerNotificationService.ts
@@ -10,23 +10,23 @@ export class PlayerNotificationService extends ServiceBase {
clientNotifier: NetworkClientNotifier = new NetworkClientNotifier();
notifyGameState(game: DominoesGame) {
- const gameState: GameState = game.getGameState();
+ const gameState: GameState = game.getState();
const { players } = game;
- players.map(player => player.sendEvent('update-game-state', gameState));
+ players.filter(p => p instanceof NetworkPlayer).map(player => player.sendEvent('update-game-state', gameState));
}
notifyPlayersState(players: PlayerInterface[]) {
- players.map(player => player.sendEvent('update-player-state', player.getState()));
+ players.filter(p => p instanceof NetworkPlayer).map(player => player.sendEvent('update-player-state', player.getState()));
}
notifyMatchState(session: MatchSession) {
const { players } = session;
- players.map(player => player.sendEvent('update-match-session-state', session.getState()));
+ players.filter(p => p instanceof NetworkPlayer).forEach(player => player.sendEvent('update-match-session-state', session.getState()));
}
async sendEventToPlayers(event: string, players: PlayerInterface[], data: Function | any = {}) {
- players.forEach((player) => {
+ players.filter(p => p instanceof NetworkPlayer).forEach((player) => {
let dataTosend = data;
if (typeof data === 'function') {
dataTosend = data(player);
@@ -37,6 +37,8 @@ export class PlayerNotificationService extends ServiceBase {
sendEvent(event: string, player: PlayerInterface, data: any = {}) {
this.logger.debug(`Sending event '${event}' to player ${player.id}`);
- this.clientNotifier.sendEvent(player as NetworkPlayer, event, data);
+ if (player instanceof NetworkPlayer) {
+ this.clientNotifier.sendEvent(player as NetworkPlayer, event, data);
+ }
}
}
\ No newline at end of file
diff --git a/src/server/services/SocketIoService.ts b/src/server/services/SocketIoService.ts
index 5ceee90..f8fa410 100644
--- a/src/server/services/SocketIoService.ts
+++ b/src/server/services/SocketIoService.ts
@@ -2,7 +2,6 @@ import { Server as HttpServer } from "http";
import { ServiceBase } from "./ServiceBase";
import { Server } from "socket.io";
import { SecurityManager } from "../managers/SecurityManager";
-import { User } from "../db/interfaces";
import { Socket } from "socket.io";
import { InteractionService } from "./InteractionService";
import { ClientEvents } from "../../game/constants";
@@ -24,7 +23,7 @@ export class SocketIoService extends ServiceBase {
if (socket.handshake.auth && socket.handshake.auth.token) {
const token = socket.handshake.auth.token;
try {
- const user: User = await this.security.verifyJwt(token);
+ const { user } = await this.security.verifyJwt(token);
socket.user = user;
next();
} catch (err) {
@@ -61,8 +60,7 @@ export class SocketIoService extends ServiceBase {
if (user !== undefined && user._id !== undefined) {
const userId = user._id.toString();
if (!SocketIoService.clients.has(userId)) {
- SocketIoService.clients.set(userId, { socketId, alive: true, user: socket.user });
- socket.join('room-general')
+ SocketIoService.clients.set(userId, { socketId, alive: true, user: socket.user });
} else {
const client = SocketIoService.clients.get(userId);
this.interactionService.updateSocketId(client.sessionId, userId, socketId);
@@ -83,6 +81,11 @@ export class SocketIoService extends ServiceBase {
}
});
+ socket.on('client:join-room', (room) => {
+ socket.join(room);
+ this.logger.debug(`User ${socket.user?.username} joined room ${room}`);
+ });
+
socket.on(ClientEvents.CLIENT_EVENT, (data) => {
this.interactionService.handleClientEvent(data);
});