This commit is contained in:
Jose Conde 2024-07-16 19:21:35 +02:00
parent 97b490c058
commit 2b54efb604
10 changed files with 73 additions and 47 deletions

View File

@ -219,7 +219,9 @@ export class DominoesGame extends EventEmitter {
isTied: this.gameTied,
winner: this.winner?.getState(true),
score: this.players.map(player => ({id: player.id, name: player.name, score: player.score})),
players: this.players.map(player => player.getState(true))
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)),
}
this.emit('game-over', summary);
}

View File

@ -6,10 +6,11 @@ import { getRandomSeed, uuid, wait, whileNot } from "../common/utilities";
import { MatchSessionState } from "./dto/MatchSessionState";
import { PlayerNotificationService } from '../server/services/PlayerNotificationService';
import seedrandom, { PRNG } from "seedrandom";
import { NetworkPlayer } from "./entities/player/NetworkPlayer";
import { PlayerHuman } from "./entities/player/PlayerHuman";
import { GameSummary } from "./dto/GameSummary";
import { PlayerMove } from "./entities/PlayerMove";
import { SessionService } from "../server/services/SessionService";
import { Score } from "../server/db/interfaces";
export class MatchSession {
@ -23,6 +24,7 @@ export class MatchSession {
private winnerIndex: number | null = null;
private clientsReady: string[] = [];
private gameSummaries: GameSummary[] = [];
private sessionService: SessionService = new SessionService();
id: string;
matchInProgress: boolean = false;
@ -148,22 +150,26 @@ export class MatchSession {
this.setScores(gameSummary || undefined);
this.checkMatchWinner();
this.resetPlayers();
if (!this.matchInProgress) {
this.status = 'end'
this.notificationService.sendEventToPlayers('server:match-finished', this.players, {
lastGame: gameSummary,
sessionState: this.getState(true),
});
} else {
this.status = 'waiting'
// await this.playerNotificationManager.notifyMatchState(this);
this.notificationService.sendEventToPlayers('server:game-finished', this.players, {
lastGame: gameSummary,
sessionState: this.getState(true)
});
this.waitingForPlayers = true;
this.startGame();
}
try {
if (!this.matchInProgress) {
this.status = 'end'
this.notificationService.sendEventToPlayers('server:match-finished', this.players, {
lastGame: gameSummary,
sessionState: this.getState(true),
});
} else {
this.status = 'waiting'
// await this.playerNotificationManager.notifyMatchState(this);
this.notificationService.sendEventToPlayers('server:game-finished', this.players, {
lastGame: gameSummary,
sessionState: this.getState(true)
});
this.waitingForPlayers = true;
this.startGame();
}
} finally {
this.sessionService.updateSession(this);
}
}
private startGame() {
@ -327,11 +333,11 @@ export class MatchSession {
};
}
getScoreBoardState() {
getScoreBoardState(): Score[] {
return Array.from(this.scoreboard).map(([name, score]) => {
const player = this.players.find(player => player.name === name);
const id = player?.id || name;
return { id, name, score };
return { id, name, score } as Score;
});
}
}

View File

@ -1,10 +1,13 @@
import { PlayerDto } from "./PlayerDto";
import { Score } from "../../server/db/interfaces";
import { PlayerDto, TileDto } from "./PlayerDto";
export interface GameSummary {
gameId: string;
isBlocked: boolean;
isTied: boolean;
winner: PlayerDto;
score: { id: string, name: string; score: number; }[],
score: Score[],
players?: PlayerDto[];
board: TileDto[]
boneyard: TileDto[]
}

View File

@ -1,3 +1,4 @@
import { Score } from "../../server/db/interfaces";
import { GameSummary } from "./GameSummary";
import { PlayerDto } from "./PlayerDto";
@ -15,7 +16,7 @@ export interface MatchSessionState {
maxPlayers: number;
numPlayers: number;
waitingSeconds: number;
scoreboard: { id: string, name: string; score: number; }[];
scoreboard: Score[];
matchWinner: PlayerDto | null;
matchInProgress: boolean;
playersReady: number,

View File

@ -13,4 +13,5 @@ export interface PlayerDto {
hand?: TileDto[];
teamedWith?: PlayerDto | null;
ready: boolean;
isHuman: boolean;
}

View File

@ -7,6 +7,7 @@ import { EventEmitter } from "stream";
import { PlayerInteractionInterface } from "../../PlayerInteractionInterface";
import { uuid } from "../../../common/utilities";
import { PlayerDto, TileDto } from "../../dto/PlayerDto";
import { PlayerHuman } from "./PlayerHuman";
export abstract class AbstractPlayer extends EventEmitter implements PlayerInterface {
hand: Tile[] = [];
@ -59,6 +60,7 @@ export abstract class AbstractPlayer extends EventEmitter implements PlayerInter
hand: this.hand.map(tile => tile.getState(showPips)),
teamedWith: this.teamedWith?.getState(showPips) ?? null,
ready: this.ready,
isHuman: this instanceof PlayerHuman
};
}
}

View File

@ -8,8 +8,8 @@ export class GameController extends BaseController {
public async createMatch(req: Request, res: Response) {
try {
const { user, body } = req;
const { sessionName, seed } = body;
const sessionId = await this.sessionService.createSession(user, sessionName, seed);
const { sessionName, seed, options } = body;
const sessionId = await this.sessionService.createSession(user, sessionName, seed, options);
res.status(201).json({ sessionId });
} catch (error) {
this.handleError(res, error);
@ -39,7 +39,7 @@ export class GameController extends BaseController {
public async getMatch(req: Request, res: Response) {
try {
const { sessionId } = req.params;
const session = this.sessionService.getSession(sessionId)
const session = await this.sessionService.getSession(sessionId)
res.status(200).json(session);
} catch (error) {
this.handleError(res, error);

View File

@ -1,20 +1,23 @@
import { MatchSession } from "../../game/MatchSession";
import { DbMatchSession } from "./interfaces";
export function matchSessionAdapter(session: MatchSession) : DbMatchSession {
export function matchSessionAdapter(session: MatchSession, showPips: boolean = false) : DbMatchSession {
const state = session.getState(showPips);
return {
id: session.id,
name: session.name || '',
creator: session.creator.id,
players: session.players.map(player => player.id),
seed: session.seed,
mode: session.mode,
pointsToWin: session.pointsToWin,
maxPlayers: session.maxPlayers,
numPlayers: session.numPlayers,
scoreboard: Array.from(session.scoreboard.entries()).map(([player, score]) => ({ player, score })),
matchWinner: session.matchWinner ? session.matchWinner.id : null,
status: session.status
id: state.id,
name: state.name || '',
creator: state.creator,
players: state.players,
seed: state.seed,
mode: state.mode,
pointsToWin: state.pointsToWin,
maxPlayers: state.maxPlayers,
numPlayers: state.numPlayers,
scoreboard: state.scoreboard,
matchWinner: state.matchWinner,
status: state.status,
matchInProgress: state.matchInProgress,
gameSummaries: state.gameSummaries,
}
}

View File

@ -1,3 +1,6 @@
import { GameSummary } from "../../game/dto/GameSummary";
import { PlayerDto } from "../../game/dto/PlayerDto";
export interface Entity {
createdAt?: number;
modifiedAt?: number;
@ -10,7 +13,8 @@ export interface EntityMongo extends Entity {
}
export interface Score {
player: string;
id: string;
name: string;
score: number;
}
@ -45,15 +49,17 @@ export interface DbMatchSession extends EntityMongo {
id: string;
name: string;
creator: string;
players: string[];
players: PlayerDto[];
seed: string;
mode: string;
pointsToWin: number;
maxPlayers: number;
numPlayers: number;
scoreboard: Score[];
matchWinner: string | null;
matchWinner: PlayerDto | null;
status: string;
matchInProgress: boolean;
gameSummaries: GameSummary[];
}
export interface DbUser extends EntityMongo {

View File

@ -10,7 +10,6 @@ import { MatchSessionMongoManager } from "../db/mongo/MatchSessionMongoManager";
import { SessionManager } from "../managers/SessionManager";
import { ServiceBase } from "./ServiceBase";
import { SocketIoService } from "./SocketIoService";
import toObjectId from "../db/mongo/common/mongoUtils";
export class SessionService extends ServiceBase{
private dbManager: MatchSessionMongoManager = new MatchSessionMongoManager();
@ -20,7 +19,7 @@ export class SessionService extends ServiceBase{
super()
}
public async createSession(user: any, sessionName: string, seed: string ): Promise<string> {
public async createSession(user: any, sessionName: string, seed: string, options: any ): Promise<string> {
let socketClient;
try {
socketClient = await whileNotUndefined(() => SocketIoService.getClient(user._id));
@ -29,6 +28,7 @@ export class SessionService extends ServiceBase{
}
const player = new NetworkPlayer(user._id, user.username, socketClient.socketId);
const session = new MatchSession(player, sessionName, seed);
session.pointsToWin = options.pointsToWin;
const dbSessionId = await this.dbManager.create(matchSessionAdapter(session));
if (dbSessionId === undefined) {
throw new SessionCreationError();
@ -82,7 +82,9 @@ export class SessionService extends ServiceBase{
return this.dbManager.update(session);
}
// public updateSession(session: MatchSession): any {
// this.dbManager.replaceOne({id: session.id}, matchSessionAdapter(session));
// }
public updateSession(session: MatchSession): any {
const entity = matchSessionAdapter(session);
entity._id = session.id
this.dbManager.update(entity);
}
}