0.1.3
This commit is contained in:
parent
d322442022
commit
39060a4064
130
.hmrc
130
.hmrc
@ -1,34 +1,134 @@
|
|||||||
{
|
{
|
||||||
"path": "G:\\Other\\Development\\Projects\\[ideas]\\domino",
|
"path": "G:\\Other\\Development\\Projects\\[ideas]\\domino",
|
||||||
"name": "domino",
|
"name": "domino-server",
|
||||||
"initialVersion": "1.0.0",
|
"initialVersion": "0.1.1",
|
||||||
"version": "1.0.0",
|
"version": "0.1.2",
|
||||||
"docker": {
|
"docker": {
|
||||||
"repository": "arhuako/domino"
|
"useRegistry": true,
|
||||||
|
"registry": "192.168.1.115:5000",
|
||||||
|
"repository": "arhuako/domino-server"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "github",
|
"type": "other",
|
||||||
"user": "jmconde",
|
"url": "https://gitea.xintanalabs.net/arhuako/domino-server.git",
|
||||||
"name": "domino",
|
"manage": true
|
||||||
"manage": true,
|
|
||||||
"createOnInit": true
|
|
||||||
},
|
},
|
||||||
"changelog": {
|
"changelog": {
|
||||||
"create": true,
|
|
||||||
"managed": true,
|
"managed": true,
|
||||||
"createHTML": true,
|
"createHTML": true,
|
||||||
"htmlPath": "public"
|
"htmlPath": "public"
|
||||||
},
|
},
|
||||||
"_backupInitial": {
|
"_backupInitial": {
|
||||||
"name": "domino",
|
"name": "domino-server",
|
||||||
"version": "1.0.0",
|
"version": "0.1.1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.6.0"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"build": "tsc",
|
||||||
|
"dev": "node --env-file=.env --watch -r ts-node/register src/server/index.ts",
|
||||||
|
"create": "node --env-file=.env -r ts-node/register ./create.ts",
|
||||||
|
"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 arhuako/domino:latest .",
|
||||||
|
"docker-tag": "docker tag arhuako/domino:latest arhuako/domino:1.0.0",
|
||||||
|
"docker-push": "docker push arhuako/domino:latest && docker push arhuako/domino:1.0.0",
|
||||||
|
"publish": "npm run docker-build && npm run docker-tag && npm run docker-push"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "arhuako",
|
||||||
"license": "ISC"
|
"license": "ISC",
|
||||||
|
"type": "commonjs",
|
||||||
|
"reposityory": "github:jmconde/domino",
|
||||||
|
"dependencies": {
|
||||||
|
"bcryptjs": "^2.4.3",
|
||||||
|
"chalk": "^4.1.2",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"express": "^4.19.2",
|
||||||
|
"express-validator": "^7.1.0",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"mongodb": "^6.8.0",
|
||||||
|
"nodemailer": "^6.9.14",
|
||||||
|
"nodemailer-express-handlebars": "^6.1.2",
|
||||||
|
"pino": "^9.2.0",
|
||||||
|
"pino-http": "^10.2.0",
|
||||||
|
"pino-pretty": "^11.2.1",
|
||||||
|
"pino-rotating-file-stream": "^0.0.2",
|
||||||
|
"pubsub-js": "^1.9.4",
|
||||||
|
"seedrandom": "^3.0.5",
|
||||||
|
"socket.io": "^4.7.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bcryptjs": "^2.4.6",
|
||||||
|
"@types/express": "^4.17.21",
|
||||||
|
"@types/jsonwebtoken": "^9.0.6",
|
||||||
|
"@types/node": "^20.14.8",
|
||||||
|
"@types/nodemailer": "^6.4.15",
|
||||||
|
"@types/nodemailer-express-handlebars": "^4.0.5",
|
||||||
|
"@types/pubsub-js": "^1.8.6",
|
||||||
|
"@types/seedrandom": "^3.0.8",
|
||||||
|
"ts-node": "^10.9.2",
|
||||||
|
"typescript": "^5.5.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"_backup": {
|
||||||
|
"name": "domino-server",
|
||||||
|
"version": "0.1.1",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.6.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"dev": "node --env-file=.env --watch -r ts-node/register src/server/index.ts",
|
||||||
|
"create": "node --env-file=.env -r ts-node/register ./create.ts",
|
||||||
|
"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.1",
|
||||||
|
"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.1",
|
||||||
|
"publish": "npm run docker-build && npm run docker-tag && npm run docker-push"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "arhuako",
|
||||||
|
"license": "ISC",
|
||||||
|
"type": "commonjs",
|
||||||
|
"reposityory": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitea.xintanalabs.net/arhuako/domino-server.git"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"bcryptjs": "^2.4.3",
|
||||||
|
"chalk": "^4.1.2",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"express": "^4.19.2",
|
||||||
|
"express-validator": "^7.1.0",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"mongodb": "^6.8.0",
|
||||||
|
"nodemailer": "^6.9.14",
|
||||||
|
"nodemailer-express-handlebars": "^6.1.2",
|
||||||
|
"pino": "^9.2.0",
|
||||||
|
"pino-http": "^10.2.0",
|
||||||
|
"pino-pretty": "^11.2.1",
|
||||||
|
"pino-rotating-file-stream": "^0.0.2",
|
||||||
|
"pubsub-js": "^1.9.4",
|
||||||
|
"seedrandom": "^3.0.5",
|
||||||
|
"socket.io": "^4.7.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/bcryptjs": "^2.4.6",
|
||||||
|
"@types/express": "^4.17.21",
|
||||||
|
"@types/jsonwebtoken": "^9.0.6",
|
||||||
|
"@types/node": "^20.14.8",
|
||||||
|
"@types/nodemailer": "^6.4.15",
|
||||||
|
"@types/nodemailer-express-handlebars": "^4.0.5",
|
||||||
|
"@types/pubsub-js": "^1.8.6",
|
||||||
|
"@types/seedrandom": "^3.0.8",
|
||||||
|
"ts-node": "^10.9.2",
|
||||||
|
"typescript": "^5.5.2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,4 +2,7 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
Initial commit
|
|
||||||
|
## 0.1.2 - 2024-07-17
|
||||||
|
### Added
|
||||||
|
- This changelog
|
||||||
|
15
package.json
15
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "domino",
|
"name": "domino-server",
|
||||||
"version": "1.0.0",
|
"version": "0.1.2",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -12,16 +12,19 @@
|
|||||||
"create": "node --env-file=.env -r ts-node/register ./create.ts",
|
"create": "node --env-file=.env -r ts-node/register ./create.ts",
|
||||||
"test": "node --env-file=.env -r ts-node/register src/test.ts",
|
"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",
|
"test:watch": "node --env-file=.env --watch -r ts-node/register src/test.ts",
|
||||||
"docker-build": "docker build -t arhuako/domino:latest .",
|
"docker-build": "docker build -t 192.168.1.115:5000/arhuako/domino-server:latest .",
|
||||||
"docker-tag": "docker tag arhuako/domino:latest arhuako/domino:1.0.0",
|
"docker-tag": "docker tag 192.168.1.115:5000/arhuako/domino-server:latest 192.168.1.115:5000/arhuako/domino-server:0.1.2",
|
||||||
"docker-push": "docker push arhuako/domino:latest && docker push arhuako/domino:1.0.0",
|
"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.2",
|
||||||
"publish": "npm run docker-build && npm run docker-tag && npm run docker-push"
|
"publish": "npm run docker-build && npm run docker-tag && npm run docker-push"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "arhuako",
|
"author": "arhuako",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
"reposityory": "github:jmconde/domino",
|
"reposityory": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitea.xintanalabs.net/arhuako/domino-server.git"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"chalk": "^4.1.2",
|
"chalk": "^4.1.2",
|
||||||
|
7
public/CHANGELOG.html
Normal file
7
public/CHANGELOG.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<h1>Changelog</h1>
|
||||||
|
<p>All notable changes to this project will be documented in this file.</p>
|
||||||
|
<h2>0.1.2 - 2024-07-17</h2>
|
||||||
|
<h3>Added</h3>
|
||||||
|
<ul>
|
||||||
|
<li>This changelog</li>
|
||||||
|
</ul>
|
@ -288,12 +288,19 @@ export class DominoesGame extends EventEmitter {
|
|||||||
if (this.winner !== null) {
|
if (this.winner !== null) {
|
||||||
const winner = this.winner;
|
const winner = this.winner;
|
||||||
winner.score = totalPips;
|
winner.score = totalPips;
|
||||||
if (winner.teamedWith !== null) {
|
if (winner.teamedWith !== undefined) {
|
||||||
winner.teamedWith.score = totalPips;
|
const p = this.getPlayer(winner.teamedWith)
|
||||||
|
if (p !== undefined) {
|
||||||
|
p.score = totalPips;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getPlayer(userId: string) {
|
||||||
|
return this.players.find(player => player.id === userId) || undefined;
|
||||||
|
}
|
||||||
|
|
||||||
private autoDealTiles() {
|
private autoDealTiles() {
|
||||||
for (let i = 0; i < this.handSize; i++) {
|
for (let i = 0; i < this.handSize; i++) {
|
||||||
for (let player of this.players) {
|
for (let player of this.players) {
|
||||||
|
@ -11,6 +11,7 @@ import { GameSummary } from "./dto/GameSummary";
|
|||||||
import { PlayerMove } from "./entities/PlayerMove";
|
import { PlayerMove } from "./entities/PlayerMove";
|
||||||
import { SessionService } from "../server/services/SessionService";
|
import { SessionService } from "../server/services/SessionService";
|
||||||
import { Score } from "../server/db/interfaces";
|
import { Score } from "../server/db/interfaces";
|
||||||
|
import { MatchSessionOptions } from "./dto/MatchSessionOptions";
|
||||||
|
|
||||||
|
|
||||||
export class MatchSession {
|
export class MatchSession {
|
||||||
@ -33,26 +34,30 @@ export class MatchSession {
|
|||||||
maxPlayers: number = 4;
|
maxPlayers: number = 4;
|
||||||
mode: string = 'classic';
|
mode: string = 'classic';
|
||||||
players: PlayerInterface[] = [];
|
players: PlayerInterface[] = [];
|
||||||
pointsToWin: number = 50;
|
// pointsToWin: number = 50;
|
||||||
rng!: PRNG
|
rng!: PRNG
|
||||||
scoreboard: Map<string, number> = new Map();
|
scoreboard: Map<string, number> = new Map();
|
||||||
seed!: string
|
seed!: string
|
||||||
sessionInProgress: boolean = false;
|
sessionInProgress: boolean = false;
|
||||||
status: string = 'created'
|
status: string = 'created'
|
||||||
|
name: string
|
||||||
|
|
||||||
constructor(public creator: PlayerInterface, public name?: string, seed?: string) {
|
constructor(public creator: PlayerInterface, private options: MatchSessionOptions) {
|
||||||
|
const { sessionName, seed, winType, winTarget } = options;
|
||||||
this.seed = seed || getRandomSeed();
|
this.seed = seed || getRandomSeed();
|
||||||
this.id = uuid();
|
this.id = uuid();
|
||||||
this.name = name || `Game ${this.id}`;
|
this.name = sessionName || `Match ${this.id}`;
|
||||||
this.addPlayerToSession(creator);
|
this.addPlayerToSession(creator);
|
||||||
this.creator = creator;
|
this.creator = creator;
|
||||||
|
|
||||||
this.logger.info(`Match session created by: ${creator.name}`);
|
this.logger.info(`Match session created by: ${creator.name}`);
|
||||||
this.logger.info(`Match session ID: ${this.id}`);
|
this.logger.info(`Match session ID: ${this.id}`);
|
||||||
this.logger.info(`Match session name: ${this.name}`);
|
this.logger.info(`Match session name: ${this.name}`);
|
||||||
this.logger.info(`Points to win: ${this.pointsToWin}`);
|
this.logger.info(`Win type: ${options.winType}`);
|
||||||
this.sessionInProgress = true;
|
this.logger.info(`Win target: ${options.winTarget}`);
|
||||||
|
this.sessionInProgress = false;
|
||||||
this.waitingForPlayers = true;
|
this.waitingForPlayers = true;
|
||||||
|
this.status = 'created';
|
||||||
this.logger.info('Waiting for players to be ready');
|
this.logger.info('Waiting for players to be ready');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +108,7 @@ export class MatchSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getPlayer(userId: string) {
|
getPlayer(userId: string) {
|
||||||
return this.players.find(player => player.id === userId);
|
return this.players.find(player => player.id === userId) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
playerMove(move: any) {
|
playerMove(move: any) {
|
||||||
@ -122,19 +127,42 @@ export class MatchSession {
|
|||||||
if (!tile) {
|
if (!tile) {
|
||||||
throw new Error("Tile not found");
|
throw new Error("Tile not found");
|
||||||
}
|
}
|
||||||
const newMove = new PlayerMove(tile, move.type, move. playerId)
|
const newMove = new PlayerMove(tile, move.type, move.playerId, move.direction)
|
||||||
this.currentGame.finishTurn(newMove);
|
this.currentGame.finishTurn(newMove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the entry point for the game, method called by session host
|
// This is the entry point for the game, method called by session host
|
||||||
async start() {
|
async start(data: any) {
|
||||||
if (this.matchInProgress) {
|
if (this.matchInProgress) {
|
||||||
throw new Error("Game already in progress");
|
throw new Error("Game already in progress");
|
||||||
}
|
}
|
||||||
this.waitingForPlayers = false;
|
this.waitingForPlayers = false;
|
||||||
|
this.sessionInProgress = true;
|
||||||
|
this.status = 'started'
|
||||||
|
this.sessionService.updateSession(this);
|
||||||
await this.startMatch(this.seed);
|
await this.startMatch(this.seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTeams(data: any) {
|
||||||
|
if (data.teamedWith !== undefined) {
|
||||||
|
const creatorTeam = this.getPlayer(data.teamedWith)
|
||||||
|
if (!creatorTeam) {
|
||||||
|
throw new Error("Teamed player not found");
|
||||||
|
}
|
||||||
|
this.creator.teamedWith = data.teamedWith;
|
||||||
|
this.creator.team = 1
|
||||||
|
creatorTeam.teamedWith = this.creator.id;
|
||||||
|
creatorTeam.team = 1;
|
||||||
|
|
||||||
|
const others = this.players.filter(player => player.team === 0);
|
||||||
|
others[0].teamedWith = others[1].id;
|
||||||
|
others[0].team = 2;
|
||||||
|
others[1].teamedWith = others[0].id;
|
||||||
|
others[1].team = 2;
|
||||||
|
this.players = [this.creator, others[0], creatorTeam, others[1]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addPlayerToSession(player: PlayerInterface) {
|
addPlayerToSession(player: PlayerInterface) {
|
||||||
if (this.numPlayers >= this.maxPlayers) {
|
if (this.numPlayers >= this.maxPlayers) {
|
||||||
@ -225,7 +253,16 @@ export class MatchSession {
|
|||||||
checkMatchWinner() {
|
checkMatchWinner() {
|
||||||
const scores = Array.from(this.scoreboard.values());
|
const scores = Array.from(this.scoreboard.values());
|
||||||
const maxScore = Math.max(...scores);
|
const maxScore = Math.max(...scores);
|
||||||
if (maxScore >= this.pointsToWin) {
|
|
||||||
|
if (this.options.winType === 'rounds') {
|
||||||
|
this.checkRoundsWinner(maxScore);
|
||||||
|
} else if (this.options.winType === 'points') {
|
||||||
|
this.checkPointsWinner(maxScore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkRoundsWinner(maxScore: number) {
|
||||||
|
if (maxScore >= this.options.winTarget) {
|
||||||
this.matchWinner = this.players.find(player => this.scoreboard.get(player.name) === maxScore);
|
this.matchWinner = this.players.find(player => this.scoreboard.get(player.name) === maxScore);
|
||||||
if (!this.matchWinner) {
|
if (!this.matchWinner) {
|
||||||
throw new Error('Match winner not found');
|
throw new Error('Match winner not found');
|
||||||
@ -234,6 +271,20 @@ export class MatchSession {
|
|||||||
this.matchInProgress = false;
|
this.matchInProgress = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkPointsWinner(maxScore: number) {
|
||||||
|
if (maxScore >= this.options.winTarget) {
|
||||||
|
this.matchWinner = this.players.find(player => this.scoreboard.get(player.name) === maxScore);
|
||||||
|
if (!this.matchWinner) {
|
||||||
|
throw new Error('Match winner not found');
|
||||||
|
}
|
||||||
|
this.logger.info(`Match winner: ${this.matchWinner.name} with ${maxScore} points`);
|
||||||
|
this.matchInProgress = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
resetScoreboard() {
|
resetScoreboard() {
|
||||||
this.scoreboard = new Map();
|
this.scoreboard = new Map();
|
||||||
this.players.forEach(player => {
|
this.players.forEach(player => {
|
||||||
@ -245,6 +296,22 @@ export class MatchSession {
|
|||||||
if (!gameSummary) {
|
if (!gameSummary) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this.options.winType === 'rounds') {
|
||||||
|
this.setScoresRounds(gameSummary);
|
||||||
|
} else if (this.options.winType === 'points') {
|
||||||
|
this.setScoresPoints(gameSummary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setScoresRounds(gameSummary: GameSummary) {
|
||||||
|
const { winner } = gameSummary;
|
||||||
|
if (winner !== undefined) {
|
||||||
|
const currentScore = this.scoreboard.get(winner.name) ?? 0;
|
||||||
|
this.scoreboard.set(winner.name, 1 + currentScore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setScoresPoints(gameSummary: GameSummary) {
|
||||||
const { score } = gameSummary;
|
const { score } = gameSummary;
|
||||||
score.forEach(playerScore => {
|
score.forEach(playerScore => {
|
||||||
const currentScore = this.scoreboard.get(playerScore.name) ?? 0;
|
const currentScore = this.scoreboard.get(playerScore.name) ?? 0;
|
||||||
@ -324,12 +391,12 @@ export class MatchSession {
|
|||||||
waitingSeconds: this.waitingSeconds,
|
waitingSeconds: this.waitingSeconds,
|
||||||
seed: this.seed,
|
seed: this.seed,
|
||||||
mode: this.mode,
|
mode: this.mode,
|
||||||
pointsToWin: this.pointsToWin,
|
status: this.status,
|
||||||
status: this.sessionInProgress ? 'in progress' : 'waiting',
|
|
||||||
scoreboard: this.getScoreBoardState(),
|
scoreboard: this.getScoreBoardState(),
|
||||||
matchWinner: this.matchWinner?.getState(true) || null,
|
matchWinner: this.matchWinner?.getState(true) || null,
|
||||||
matchInProgress: this.matchInProgress,
|
matchInProgress: this.matchInProgress,
|
||||||
gameSummaries: this.gameSummaries,
|
gameSummaries: this.gameSummaries,
|
||||||
|
options: this.options,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
src/game/dto/MatchSessionOptions.ts
Normal file
13
src/game/dto/MatchSessionOptions.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
export interface MatchSessionOptions {
|
||||||
|
boardScale?: number
|
||||||
|
handScale?: number
|
||||||
|
width?: number
|
||||||
|
height?: number
|
||||||
|
background: string
|
||||||
|
teamed: boolean
|
||||||
|
winTarget: number
|
||||||
|
winType: 'points' | 'rounds'
|
||||||
|
seed: string
|
||||||
|
sessionName: string
|
||||||
|
numPlayers: 1 | 2 | 3 | 4
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import { Score } from "../../server/db/interfaces";
|
import { Score } from "../../server/db/interfaces";
|
||||||
import { GameSummary } from "./GameSummary";
|
import { GameSummary } from "./GameSummary";
|
||||||
|
import { MatchSessionOptions } from "./MatchSessionOptions";
|
||||||
import { PlayerDto } from "./PlayerDto";
|
import { PlayerDto } from "./PlayerDto";
|
||||||
|
|
||||||
export interface MatchSessionState {
|
export interface MatchSessionState {
|
||||||
@ -10,7 +11,6 @@ export interface MatchSessionState {
|
|||||||
seed: string;
|
seed: string;
|
||||||
waitingForPlayers: boolean;
|
waitingForPlayers: boolean;
|
||||||
mode: string;
|
mode: string;
|
||||||
pointsToWin: number;
|
|
||||||
sessionInProgress: boolean;
|
sessionInProgress: boolean;
|
||||||
status: string;
|
status: string;
|
||||||
maxPlayers: number;
|
maxPlayers: number;
|
||||||
@ -21,4 +21,5 @@ export interface MatchSessionState {
|
|||||||
matchInProgress: boolean;
|
matchInProgress: boolean;
|
||||||
playersReady: number,
|
playersReady: number,
|
||||||
gameSummaries: GameSummary[];
|
gameSummaries: GameSummary[];
|
||||||
|
options: MatchSessionOptions
|
||||||
}
|
}
|
@ -11,7 +11,7 @@ export interface PlayerDto {
|
|||||||
name: string;
|
name: string;
|
||||||
score?: number;
|
score?: number;
|
||||||
hand?: TileDto[];
|
hand?: TileDto[];
|
||||||
teamedWith?: PlayerDto | null;
|
teamedWith?: string;
|
||||||
ready: boolean;
|
ready: boolean;
|
||||||
isHuman: boolean;
|
isHuman: boolean;
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ import { Tile } from "./Tile";
|
|||||||
|
|
||||||
export class PlayerMove {
|
export class PlayerMove {
|
||||||
id: string = uuid();
|
id: string = uuid();
|
||||||
constructor(public tile: Tile, public type: PlayerMoveSideType | null, public playerId: string, direction?: string) {}
|
constructor(public tile: Tile, public type: PlayerMoveSideType | null, public playerId: string, public direction?: string) {}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
return `PlayerMove:([${this.tile.pips[0]}|${this.tile.pips[1]}] ${this.type})`;
|
return `PlayerMove:([${this.tile.pips[0]}|${this.tile.pips[1]}] ${this.type})`;
|
||||||
|
@ -13,10 +13,11 @@ export abstract class AbstractPlayer extends EventEmitter implements PlayerInter
|
|||||||
hand: Tile[] = [];
|
hand: Tile[] = [];
|
||||||
score: number = 0;
|
score: number = 0;
|
||||||
logger: LoggingService = new LoggingService();
|
logger: LoggingService = new LoggingService();
|
||||||
teamedWith: PlayerInterface | null = null;
|
teamedWith?: string;
|
||||||
playerInteraction: PlayerInteractionInterface = undefined as any;
|
playerInteraction: PlayerInteractionInterface = undefined as any;
|
||||||
id: string = uuid();
|
id: string = uuid();
|
||||||
ready: boolean = false;
|
ready: boolean = false;
|
||||||
|
team: number = 0;
|
||||||
|
|
||||||
constructor(public name: string) {
|
constructor(public name: string) {
|
||||||
super();
|
super();
|
||||||
@ -58,7 +59,7 @@ export abstract class AbstractPlayer extends EventEmitter implements PlayerInter
|
|||||||
name: this.name,
|
name: this.name,
|
||||||
score: this.score,
|
score: this.score,
|
||||||
hand: this.hand.map(tile => tile.getState(showPips)),
|
hand: this.hand.map(tile => tile.getState(showPips)),
|
||||||
teamedWith: this.teamedWith?.getState(showPips) ?? null,
|
teamedWith: this.teamedWith,
|
||||||
ready: this.ready,
|
ready: this.ready,
|
||||||
isHuman: this instanceof PlayerHuman
|
isHuman: this instanceof PlayerHuman
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,8 @@ export interface PlayerInterface {
|
|||||||
name: string;
|
name: string;
|
||||||
score: number;
|
score: number;
|
||||||
hand: Tile[];
|
hand: Tile[];
|
||||||
teamedWith: PlayerInterface | null;
|
teamedWith?: string;
|
||||||
|
team: number;
|
||||||
playerInteraction: PlayerInteractionInterface;
|
playerInteraction: PlayerInteractionInterface;
|
||||||
ready: boolean;
|
ready: boolean;
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@ export class GameController extends BaseController {
|
|||||||
public async createMatch(req: Request, res: Response) {
|
public async createMatch(req: Request, res: Response) {
|
||||||
try {
|
try {
|
||||||
const { user, body } = req;
|
const { user, body } = req;
|
||||||
const { sessionName, seed, options } = body;
|
const { options } = body;
|
||||||
const sessionId = await this.sessionService.createSession(user, sessionName, seed, options);
|
const sessionId = await this.sessionService.createSession(user, options);
|
||||||
res.status(201).json({ sessionId });
|
res.status(201).json({ sessionId });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleError(res, error);
|
this.handleError(res, error);
|
||||||
|
@ -10,7 +10,7 @@ export function matchSessionAdapter(session: MatchSession, showPips: boolean = f
|
|||||||
players: state.players,
|
players: state.players,
|
||||||
seed: state.seed,
|
seed: state.seed,
|
||||||
mode: state.mode,
|
mode: state.mode,
|
||||||
pointsToWin: state.pointsToWin,
|
options: state.options,
|
||||||
maxPlayers: state.maxPlayers,
|
maxPlayers: state.maxPlayers,
|
||||||
numPlayers: state.numPlayers,
|
numPlayers: state.numPlayers,
|
||||||
scoreboard: state.scoreboard,
|
scoreboard: state.scoreboard,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { GameSummary } from "../../game/dto/GameSummary";
|
import { GameSummary } from "../../game/dto/GameSummary";
|
||||||
|
import { MatchSessionOptions } from "../../game/dto/MatchSessionOptions";
|
||||||
import { PlayerDto } from "../../game/dto/PlayerDto";
|
import { PlayerDto } from "../../game/dto/PlayerDto";
|
||||||
|
|
||||||
export interface Entity {
|
export interface Entity {
|
||||||
@ -52,7 +53,7 @@ export interface DbMatchSession extends EntityMongo {
|
|||||||
players: PlayerDto[];
|
players: PlayerDto[];
|
||||||
seed: string;
|
seed: string;
|
||||||
mode: string;
|
mode: string;
|
||||||
pointsToWin: number;
|
options: MatchSessionOptions;
|
||||||
maxPlayers: number;
|
maxPlayers: number;
|
||||||
numPlayers: number;
|
numPlayers: number;
|
||||||
scoreboard: Score[];
|
scoreboard: Score[];
|
||||||
|
@ -64,10 +64,11 @@ export class InteractionService extends ServiceBase{
|
|||||||
for (let i = 0; i < missingHumans; i++) {
|
for (let i = 0; i < missingHumans; i++) {
|
||||||
session.addPlayerToSession(session.createPlayerAI(i));
|
session.addPlayerToSession(session.createPlayerAI(i));
|
||||||
}
|
}
|
||||||
|
session.setTeams(data);
|
||||||
this.notifyService.sendEventToPlayers('server:match-starting', session.players, {
|
this.notifyService.sendEventToPlayers('server:match-starting', session.players, {
|
||||||
sessionState: session.getState()
|
sessionState: session.getState()
|
||||||
});
|
});
|
||||||
session.start();
|
session.start(data);
|
||||||
return {
|
return {
|
||||||
status: 'ok'
|
status: 'ok'
|
||||||
};
|
};
|
||||||
|
@ -10,6 +10,7 @@ import { MatchSessionMongoManager } from "../db/mongo/MatchSessionMongoManager";
|
|||||||
import { SessionManager } from "../managers/SessionManager";
|
import { SessionManager } from "../managers/SessionManager";
|
||||||
import { ServiceBase } from "./ServiceBase";
|
import { ServiceBase } from "./ServiceBase";
|
||||||
import { SocketIoService } from "./SocketIoService";
|
import { SocketIoService } from "./SocketIoService";
|
||||||
|
import { MatchSessionOptions } from "../../game/dto/MatchSessionOptions";
|
||||||
|
|
||||||
export class SessionService extends ServiceBase{
|
export class SessionService extends ServiceBase{
|
||||||
private dbManager: MatchSessionMongoManager = new MatchSessionMongoManager();
|
private dbManager: MatchSessionMongoManager = new MatchSessionMongoManager();
|
||||||
@ -19,7 +20,7 @@ export class SessionService extends ServiceBase{
|
|||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createSession(user: any, sessionName: string, seed: string, options: any ): Promise<string> {
|
public async createSession(user: any, options: MatchSessionOptions ): Promise<string> {
|
||||||
let socketClient;
|
let socketClient;
|
||||||
try {
|
try {
|
||||||
socketClient = await whileNotUndefined(() => SocketIoService.getClient(user._id));
|
socketClient = await whileNotUndefined(() => SocketIoService.getClient(user._id));
|
||||||
@ -27,8 +28,7 @@ export class SessionService extends ServiceBase{
|
|||||||
throw new SessionCreationError();
|
throw new SessionCreationError();
|
||||||
}
|
}
|
||||||
const player = new NetworkPlayer(user._id, user.username, socketClient.socketId);
|
const player = new NetworkPlayer(user._id, user.username, socketClient.socketId);
|
||||||
const session = new MatchSession(player, sessionName, seed);
|
const session = new MatchSession(player, options);
|
||||||
session.pointsToWin = options.pointsToWin;
|
|
||||||
const dbSessionId = await this.dbManager.create(matchSessionAdapter(session));
|
const dbSessionId = await this.dbManager.create(matchSessionAdapter(session));
|
||||||
if (dbSessionId === undefined) {
|
if (dbSessionId === undefined) {
|
||||||
throw new SessionCreationError();
|
throw new SessionCreationError();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user