222 lines
3.9 KiB
JavaScript
222 lines
3.9 KiB
JavaScript
const EventEmitter = require('events').EventEmitter;
|
|
const Logger = require('./Logger');
|
|
|
|
const logger = new Logger('Lobby');
|
|
|
|
class Lobby extends EventEmitter
|
|
{
|
|
constructor()
|
|
{
|
|
logger.info('constructor()');
|
|
|
|
super();
|
|
|
|
// Closed flag.
|
|
this._closed = false;
|
|
|
|
this._peers = {};
|
|
}
|
|
|
|
close()
|
|
{
|
|
logger.info('close()');
|
|
|
|
this._closed = true;
|
|
|
|
// Close the peers.
|
|
for (const peer in this._peers)
|
|
{
|
|
if (!this._peers[peer].closed)
|
|
this._peers[peer].close();
|
|
}
|
|
|
|
this._peers = null;
|
|
}
|
|
|
|
checkEmpty()
|
|
{
|
|
logger.info('checkEmpty()');
|
|
|
|
return Object.keys(this._peers).length === 0;
|
|
}
|
|
|
|
peerList()
|
|
{
|
|
logger.info('peerList()');
|
|
|
|
return Object.values(this._peers).map((peer) =>
|
|
({
|
|
id : peer.id,
|
|
displayName : peer.displayName,
|
|
picture : peer.picture
|
|
}));
|
|
}
|
|
|
|
hasPeer(peerId)
|
|
{
|
|
return this._peers[peerId] != null;
|
|
}
|
|
|
|
promoteAllPeers()
|
|
{
|
|
logger.info('promoteAllPeers()');
|
|
|
|
for (const peer in this._peers)
|
|
{
|
|
if (!this._peers[peer].closed)
|
|
this.promotePeer(peer);
|
|
}
|
|
}
|
|
|
|
promotePeer(peerId)
|
|
{
|
|
logger.info('promotePeer() [peer:"%s"]', peerId);
|
|
|
|
const peer = this._peers[peerId];
|
|
|
|
if (peer)
|
|
{
|
|
peer.socket.removeListener('request', peer.socketRequestHandler);
|
|
peer.removeListener('gotRole', peer.gotRoleHandler);
|
|
peer.removeListener('displayNameChanged', peer.displayNameChangeHandler);
|
|
peer.removeListener('pictureChanged', peer.pictureChangeHandler);
|
|
peer.removeListener('close', peer.closeHandler);
|
|
|
|
peer.socketRequestHandler = null;
|
|
peer.gotRoleHandler = null;
|
|
peer.displayNameChangeHandler = null;
|
|
peer.pictureChangeHandler = null;
|
|
peer.closeHandler = null;
|
|
|
|
this.emit('promotePeer', peer);
|
|
delete this._peers[peerId];
|
|
}
|
|
}
|
|
|
|
parkPeer(peer)
|
|
{
|
|
logger.info('parkPeer() [peer:"%s"]', peer.id);
|
|
|
|
if (this._closed)
|
|
return;
|
|
|
|
peer.socketRequestHandler = (request, cb) =>
|
|
{
|
|
logger.debug(
|
|
'Peer "request" event [method:"%s", peer:"%s"]',
|
|
request.method, peer.id);
|
|
|
|
if (this._closed)
|
|
return;
|
|
|
|
this._handleSocketRequest(peer, request, cb)
|
|
.catch((error) =>
|
|
{
|
|
logger.error('request failed [error:"%o"]', error);
|
|
|
|
cb(error);
|
|
});
|
|
};
|
|
|
|
peer.gotRoleHandler = () =>
|
|
{
|
|
logger.info('parkPeer() | rolesChange [peer:"%s"]', peer.id);
|
|
|
|
this.emit('peerRolesChanged', peer);
|
|
};
|
|
|
|
peer.displayNameChangeHandler = () =>
|
|
{
|
|
logger.info('parkPeer() | displayNameChange [peer:"%s"]', peer.id);
|
|
|
|
this.emit('changeDisplayName', peer);
|
|
};
|
|
|
|
peer.pictureChangeHandler = () =>
|
|
{
|
|
logger.info('parkPeer() | pictureChange [peer:"%s"]', peer.id);
|
|
|
|
this.emit('changePicture', peer);
|
|
};
|
|
|
|
peer.closeHandler = () =>
|
|
{
|
|
logger.debug('Peer "close" event [peer:"%s"]', peer.id);
|
|
|
|
if (this._closed)
|
|
return;
|
|
|
|
this.emit('peerClosed', peer);
|
|
|
|
delete this._peers[peer.id];
|
|
|
|
if (this.checkEmpty())
|
|
this.emit('lobbyEmpty');
|
|
};
|
|
|
|
this._peers[peer.id] = peer;
|
|
|
|
peer.on('gotRole', peer.gotRoleHandler);
|
|
peer.on('displayNameChanged', peer.displayNameChangeHandler);
|
|
peer.on('pictureChanged', peer.pictureChangeHandler);
|
|
|
|
peer.socket.on('request', peer.socketRequestHandler);
|
|
|
|
peer.on('close', peer.closeHandler);
|
|
|
|
this._notification(peer.socket, 'enteredLobby');
|
|
}
|
|
|
|
async _handleSocketRequest(peer, request, cb)
|
|
{
|
|
logger.debug(
|
|
'_handleSocketRequest [peer:"%s"], [request:"%s"]',
|
|
peer.id,
|
|
request.method
|
|
);
|
|
|
|
if (this._closed)
|
|
return;
|
|
|
|
switch (request.method)
|
|
{
|
|
case 'changeDisplayName':
|
|
{
|
|
const { displayName } = request.data;
|
|
|
|
peer.displayName = displayName;
|
|
|
|
cb();
|
|
|
|
break;
|
|
}
|
|
|
|
case 'changePicture':
|
|
{
|
|
const { picture } = request.data;
|
|
|
|
peer.picture = picture;
|
|
|
|
cb();
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
_notification(socket, method, data = {}, broadcast = false)
|
|
{
|
|
if (broadcast)
|
|
{
|
|
socket.broadcast.to(this._roomId).emit(
|
|
'notification', { method, data }
|
|
);
|
|
}
|
|
else
|
|
{
|
|
socket.emit('notification', { method, data });
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = Lobby; |