authoritative server OK

+ TODO actual matchmaking
This commit is contained in:
LuckyLaszlo
2022-11-21 19:46:25 +01:00
parent 48665cfe30
commit add08c216f
20 changed files with 485 additions and 240 deletions

View File

@@ -1,29 +1,141 @@
import { ClientPlayer } from "./Client";
import {gameUpdate} from "../gameUpdate.js"
import { GameComponentsServer } from "./GameComponentsServer";
// Empty object replacement to the web-API (web-API useless on server-side)
import { GameComponents } from "../../shared_js/class/GameComponents.js";
import { clientInputListener } from "../wsServer.js";
import * as c from "../constants.js"
import { GameComponentsServer } from "./GameComponentsServer.js";
import { random } from "../../shared_js/utils.js";
import * as en from "../../shared_js/enums.js"
import * as ev from "../../shared_js/class/Event.js"
/*
Arg "s: GameSession" replace "this: GameSession" for use with setTimeout(),
because "this" is equal to "this: Timeout"
*/
class GameSession {
id: string; // url ?
playersMap: Map<string, ClientPlayer>;
unreadyPlayersMap: Map<string, ClientPlayer>;
updateInterval: NodeJS.Timer;
// gc: GameComponentsServer;
// updateInterval: NodeJS.Timer;
gameLoopInterval: NodeJS.Timer | number;
clientsUpdateInterval: NodeJS.Timer | number;
components: GameComponentsServer;
actual_time: number;
last_time: number;
delta_time: number;
constructor(id: string) {
this.id = id;
this.playersMap = new Map();
this.unreadyPlayersMap = new Map();
// this.gc = new GameComponentsServer();
this.components = new GameComponentsServer();
}
start() {
this.updateInterval = setInterval( () => {
const update = gameUpdate();
this.playersMap.forEach( (client) => {
client.socket.send(JSON.stringify(update));
});
}, 500);
setTimeout(this.resume, c.matchStartDelay, this);
setTimeout(this._newRound, c.matchStartDelay + c.newRoundDelay, this);
}
resume(s: GameSession) {
s.playersMap.forEach( (client) => {
client.socket.on("message", clientInputListener);
});
s.actual_time = Date.now();
s.gameLoopInterval = setInterval(s._gameLoop, c.gameLoopIntervalMS, s);
s.clientsUpdateInterval = setInterval(s._clientsUpdate, c.clientsUpdateIntervalMS, s);
}
pause(s: GameSession) {
s.playersMap.forEach( (client) => {
client.socket.off("message", clientInputListener);
});
clearInterval(s.gameLoopInterval);
clearInterval(s.clientsUpdateInterval);
}
handleInput(client: ClientPlayer, input: en.InputEnum) {
const gc = this.components;
client.racket.dir.y = 0;
if (input === en.InputEnum.up) {
client.racket.dir.y += -1;
}
else if (input === en.InputEnum.down) {
client.racket.dir.y += 1;
}
client.racket.moveAndCollide(this.delta_time, [gc.wallTop, gc.wallBottom]);
/* how to handle Delta time correctly in handleInput ? */
}
private _gameLoop(s: GameSession) {
s.last_time = s.actual_time;
s.actual_time = Date.now();
s.delta_time = (s.actual_time - s.last_time) / 1000;
const gc = s.components;
if (gc.ballInPlay)
{
gc.ball.moveAndBounce(s.delta_time, [gc.wallTop, gc.wallBottom, gc.playerLeft, gc.playerRight]);
if (gc.ball.pos.x > c.w) {
gc.ballInPlay = false;
++gc.scoreLeft;
s.playersMap.forEach( (client) => {
client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight)));
});
setTimeout(s._newRound, c.newRoundDelay, s);
}
else if (gc.ball.pos.x < 0 - gc.ball.width) {
gc.ballInPlay = false;
++gc.scoreRight;
s.playersMap.forEach( (client) => {
client.socket.send(JSON.stringify(new ev.EventScoreUpdate(gc.scoreLeft, gc.scoreRight)));
});
setTimeout(s._newRound, c.newRoundDelay, s);
}
}
}
private _clientsUpdate(s: GameSession) {
const gc = s.components;
const update: ev.EventGameUpdate = {
type: en.EventTypes.gameUpdate,
playerLeft: {y: gc.playerLeft.pos.y},
playerRight: {y: gc.playerRight.pos.y},
ball: {x: gc.ball.pos.x, y: gc.ball.pos.y, speed: gc.ball.speed}
};
s.playersMap.forEach( (client) => {
client.socket.send(JSON.stringify(update));
});
}
private _newRound(s: GameSession) {
const gc = s.components;
// https://fr.wikipedia.org/wiki/Tennis_de_table#Nombre_de_manches
if (gc.scoreLeft >= 11
|| gc.scoreRight >= 11)
{
if (Math.abs(gc.scoreLeft - gc.scoreRight) >= 2)
{
s._matchEnd(s);
return;
}
}
gc.ball.pos.x = c.w_mid;
gc.ball.pos.y = Math.floor((c.h * 0.1) + random() * (c.h * 0.8));
gc.ball.speed = gc.ball.baseSpeed;
gc.ballInPlay = true;
}
private _matchEnd(s: GameSession) {
const gc = s.components;
let eventEnd: ev.EventMatchEnd;
if (gc.scoreLeft > gc.scoreRight) {
eventEnd = new ev.EventMatchEnd(en.PlayerSide.left);
console.log("Player Left WIN");
}
else {
eventEnd = new ev.EventMatchEnd(en.PlayerSide.right);
console.log("Player Right WIN");
}
s.playersMap.forEach( (client) => {
client.socket.send(JSON.stringify(eventEnd));
});
}
}