gamelet-cli
Version:
Download project from code.gamelet.com, edit/test in vscode and sync back to server.
276 lines • 21.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GameroomBase = void 0;
const Message_1 = require("../messages/Message");
const ArrayUtil_1 = require("./../utils/ArrayUtil");
const events_1 = require("events");
const MonitorManager_1 = require("../managers/MonitorManager");
class GameroomBase extends events_1.EventEmitter {
constructor(roomType, code, server, client, stateJson) {
super();
this.roomType = roomType;
this.code = code;
this.server = server;
this.client = client;
this.stateJson = stateJson;
this.players = [];
// private states for each player, playerCode: object
this.playerStates = {};
this.createTime = Math.floor(Date.now() / 1000);
this.stateJson = this.stateJson || {};
}
setFpsDirty() {
this.ping = null;
}
getPing() {
if (!this.ping) {
if (this.players.length) {
let min = 9999;
let max = 0;
let total = 0;
for (let p of this.players) {
min = Math.min(min, p.networkDelay);
max = Math.max(max, p.networkDelay);
total += p.networkDelay;
}
this.ping = {
min: min,
max: max,
avg: Math.round(total / this.players.length),
};
}
else {
this.ping = {
min: 0,
max: 0,
avg: 0,
};
}
}
return this.ping;
}
get monitorChannel() {
return this.code;
}
dispose() {
this.listPlayers().forEach(player => this.removePlayer(player));
this.emit(GameroomBase.EVENT.DISPOSED);
MonitorManager_1.monitorManager.log(this.client.project.code, this.monitorChannel, this.roomType + ' disposed', this.code);
}
setPlayerSynced(player, value, updateBrainer) {
let promise;
if (this.setPlayerState(player, 'synced', value, false)) {
if (updateBrainer) {
promise = this.updateBrainer(true);
}
}
return (promise || Promise.resolve()).then(() => {
this.emit(GameroomBase.EVENT.PLAYER_SYNCED_CHANGED, player, value, this.brainer.code);
});
}
isPlayerSynced(player) {
return !!this.getPlayerState(player, 'synced');
}
setPlayerState(player, key, value, emitEvent = true) {
if (this.players.includes(player)) {
let states = this.playerStates[player.code];
if (!states) {
this.playerStates[player.code] = states = {};
}
if (this._setPlayerState(states, key, value)) {
emitEvent && this.emit(GameroomBase.EVENT.PLAYER_STATE_CHANGED, player, key, value);
return true;
}
}
else {
throw new Error('Tried to set player state of a player who is not in this ' + this.roomType);
}
return false;
}
_setPlayerState(states, key, value) {
if (states[key] !== value) {
if (value === undefined || value === null) {
value = null;
delete states[key];
}
else {
states[key] = value;
}
return true;
}
return false;
}
setPlayerStates(player, newStates) {
if (this.players.includes(player)) {
let result = false;
if (newStates) {
let states = this.playerStates[player.code];
if (!states) {
this.playerStates[player.code] = states = {};
}
for (let key in newStates) {
if (this._setPlayerState(states, key, newStates[key])) {
result = true;
}
}
}
else if (this.playerStates[player.code]) {
result = true;
this.deletePlayerState(player);
}
if (result) {
this.emit(GameroomBase.EVENT.PLAYER_STATES_CHANGED, player, newStates);
}
}
else {
throw new Error('Tried to set player state of a player who is not in this ' + this.roomType);
}
return false;
}
getPlayer(code) {
return this.players.find(p => p.code == code);
}
includesPlayer(player) {
return this.players.includes(player);
}
getPlayerState(player, key) {
let state = this.playerStates[player.code];
return state && state[key];
}
getPlayerStates(player) {
return this.playerStates[player.code];
}
deletePlayerState(player) {
if (this.playerStates[player.code]) {
delete this.playerStates[player.code];
return true;
}
else {
return false;
}
}
listPlayers() {
return this.players.slice();
}
getPlayersStates() {
return this.playerStates;
}
get playersCount() {
return this.players.length;
}
get socketChannel() {
return this.code;
}
addPlayer(player) {
if (ArrayUtil_1.ArrayUtil.addUniqueElement(this.players, player)) {
this.setFpsDirty();
if (!this.brainer) {
this.updateBrainer(false);
}
player.socket.join(this.socketChannel);
this.emit(GameroomBase.EVENT.PLAYER_ADDED, player);
this.emit(GameroomBase.EVENT.STATUS_CHANGED);
return true;
}
return false;
}
removePlayer(player) {
if (ArrayUtil_1.ArrayUtil.removeElement(this.players, player)) {
this.setFpsDirty();
player.socket.leave(this.socketChannel);
if (this.deletePlayerState(player)) {
this.emit(GameroomBase.EVENT.PLAYER_STATES_CHANGED, player, null);
}
if (player == this.brainer) {
// must do this before we send playerLeft event
this.updateBrainer(false);
}
this.emit(GameroomBase.EVENT.STATUS_CHANGED);
this.emit(GameroomBase.EVENT.PLAYER_REMOVED, player);
return true;
}
return false;
}
setBrainerByPlayer(playerCode, needPreset) {
let brainer = this.players.find(p => p.code == playerCode);
if (!brainer) {
throw new Error('The player is not in room.');
}
return this._setBrainer(brainer, needPreset);
}
updateBrainer(needPreset) {
return this._setBrainer(this.chooseBrainer(), needPreset);
}
_setBrainer(brainer, needPreset) {
if (brainer != this.brainer) {
if (needPreset) {
return brainer.send(Message_1.Message.forRoomBrainerSet(this.code))
.then(() => {
this.brainer = brainer;
this.emit(GameroomBase.EVENT.BRAINER_CHANGED);
return this.brainer;
});
}
else {
this.brainer = brainer;
this.emit(GameroomBase.EVENT.BRAINER_CHANGED);
}
}
return Promise.resolve(this.brainer);
}
chooseBrainer() {
if (this.players.length) {
let idleStart = Date.now() - 10000;
let brainer = this.players[0];
let bestDelay = this.calcNetworkDelayValue(brainer, idleStart);
for (let i = this.players.length - 1; i > 0; --i) {
let player = this.players[i];
if (this.isPlayerSynced(player)) {
let delay = this.calcNetworkDelayValue(player, idleStart);
if (player.cheats) {
delay += 500;
}
if (delay < bestDelay) {
brainer = player;
bestDelay = delay;
}
}
}
return brainer;
}
return null;
}
/**
* network delay + idle factor
*/
calcNetworkDelayValue(player, idleStart) {
let value = player.networkDelay;
if (idleStart > player.lastMsgTime) {
value += (idleStart - player.lastMsgTime) / 100;
}
return value;
}
getBrainer() {
return this.brainer;
}
broadcast(msg) {
MonitorManager_1.monitorManager.logOutgoing(this.client.project.code, this.monitorChannel, this.roomType + '.broadcast', [this.code, msg.type, msg.params]);
msg.send(this.server.to(this.socketChannel));
}
broadcastByPlayer(msg, sender) {
MonitorManager_1.monitorManager.logIncoming(this.client.project.code, this.monitorChannel, this.roomType + '.broadcast', [this.code, msg.type, msg.params], sender);
msg.send(this.server.to(this.socketChannel));
}
}
exports.GameroomBase = GameroomBase;
GameroomBase.EVENT = {
DISPOSED: 'disposed',
PLAYER_ADDED: 'playerAdded',
PLAYER_REMOVED: 'playerRemoved',
BRAINER_CHANGED: 'brainerChanged',
STATUS_CHANGED: 'statusChanged',
PLAYER_STATE_CHANGED: 'playerStateChanged',
PLAYER_STATES_CHANGED: 'playerStatesChanged',
PLAYER_SYNCED_CHANGED: 'playerSyncedChanged',
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiR2FtZXJvb21CYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3NlcnZlci9lbnRpdGllcy9HYW1lcm9vbUJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsaURBQThDO0FBQzlDLG9EQUFpRDtBQUVqRCxtQ0FBc0M7QUFDdEMsK0RBQTREO0FBRTVELE1BQWEsWUFBYSxTQUFRLHFCQUFZO0lBd0IxQyxZQUFtQixRQUFnQixFQUN4QixJQUFZLEVBQ1gsTUFBMEIsRUFDM0IsTUFBYyxFQUNkLFNBQWtDO1FBRXpDLEtBQUssRUFBRSxDQUFDO1FBTk8sYUFBUSxHQUFSLFFBQVEsQ0FBUTtRQUN4QixTQUFJLEdBQUosSUFBSSxDQUFRO1FBQ1gsV0FBTSxHQUFOLE1BQU0sQ0FBb0I7UUFDM0IsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLGNBQVMsR0FBVCxTQUFTLENBQXlCO1FBYm5DLFlBQU8sR0FBYSxFQUFFLENBQUM7UUFJakMscURBQXFEO1FBQzNDLGlCQUFZLEdBQThDLEVBQUUsQ0FBQztRQUVoRSxlQUFVLEdBQVcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFTdEQsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQztJQUMxQyxDQUFDO0lBRUQsV0FBVztRQUNQLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ3JCLENBQUM7SUFFRCxPQUFPO1FBQ0gsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNiLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDdEIsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDO2dCQUNmLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQztnQkFDWixJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7Z0JBQ2QsS0FBSyxJ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