|
|
|
@@ -1,5 +1,3 @@
|
|
|
|
|
import socketIO = require('socket.io');
|
|
|
|
|
import {Socket} from "socket.io";
|
|
|
|
|
import * as http from "http";
|
|
|
|
|
import {MessageUserPosition, Point} from "../Model/Websocket/MessageUserPosition"; //TODO fix import by "_Model/.."
|
|
|
|
|
import {ExSocketInterface} from "../Model/Websocket/ExSocketInterface"; //TODO fix import by "_Model/.."
|
|
|
|
@@ -32,11 +30,19 @@ import {
|
|
|
|
|
GroupDeleteMessage,
|
|
|
|
|
UserJoinedMessage,
|
|
|
|
|
UserLeftMessage,
|
|
|
|
|
ItemEventMessage, ViewportMessage
|
|
|
|
|
ItemEventMessage,
|
|
|
|
|
ViewportMessage,
|
|
|
|
|
ClientToServerMessage,
|
|
|
|
|
JoinRoomMessage,
|
|
|
|
|
ErrorMessage,
|
|
|
|
|
RoomJoinedMessage,
|
|
|
|
|
ItemStateMessage,
|
|
|
|
|
ServerToClientMessage, SetUserIdMessage, SilentMessage
|
|
|
|
|
} from "../Messages/generated/messages_pb";
|
|
|
|
|
import {UserMovesMessage} from "../Messages/generated/messages_pb";
|
|
|
|
|
import Direction = PositionMessage.Direction;
|
|
|
|
|
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
|
|
|
|
|
import {App, TemplatedApp, WebSocket} from "uWebSockets.js"
|
|
|
|
|
|
|
|
|
|
enum SocketIoEvent {
|
|
|
|
|
CONNECTION = "connection",
|
|
|
|
@@ -59,12 +65,18 @@ enum SocketIoEvent {
|
|
|
|
|
BATCH = "batch",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function emitInBatch(socket: ExSocketInterface, event: string, payload: SubMessage): void {
|
|
|
|
|
function emitInBatch(socket: ExSocketInterface, payload: SubMessage): void {
|
|
|
|
|
if (socket.disconnecting) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
socket.batchedMessages.addPayload(payload);
|
|
|
|
|
|
|
|
|
|
if (socket.batchTimeout === null) {
|
|
|
|
|
socket.batchTimeout = setTimeout(() => {
|
|
|
|
|
socket./*binary(true).*/emit(SocketIoEvent.BATCH, socket.batchedMessages.serializeBinary().buffer);
|
|
|
|
|
const serverToClientMessage = new ServerToClientMessage();
|
|
|
|
|
serverToClientMessage.setBatchmessage(socket.batchedMessages);
|
|
|
|
|
|
|
|
|
|
socket.send(serverToClientMessage.serializeBinary().buffer, true);
|
|
|
|
|
socket.batchedMessages = new BatchMessage();
|
|
|
|
|
socket.batchTimeout = null;
|
|
|
|
|
}, 100);
|
|
|
|
@@ -72,15 +84,14 @@ function emitInBatch(socket: ExSocketInterface, event: string, payload: SubMessa
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class IoSocketController {
|
|
|
|
|
public readonly Io: socketIO.Server;
|
|
|
|
|
private Worlds: Map<string, World> = new Map<string, World>();
|
|
|
|
|
private sockets: Map<number, ExSocketInterface> = new Map<number, ExSocketInterface>();
|
|
|
|
|
private nbClientsGauge: Gauge<string>;
|
|
|
|
|
private nbClientsPerRoomGauge: Gauge<string>;
|
|
|
|
|
private nextUserId: number = 1;
|
|
|
|
|
|
|
|
|
|
constructor(server: http.Server) {
|
|
|
|
|
this.Io = socketIO(server);
|
|
|
|
|
constructor(private readonly app: TemplatedApp) {
|
|
|
|
|
|
|
|
|
|
this.nbClientsGauge = new Gauge({
|
|
|
|
|
name: 'workadventure_nb_sockets',
|
|
|
|
|
help: 'Number of connected sockets',
|
|
|
|
@@ -92,52 +103,6 @@ export class IoSocketController {
|
|
|
|
|
labelNames: [ 'room' ]
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Authentication with token. it will be decoded and stored in the socket.
|
|
|
|
|
// Completely commented for now, as we do not use the "/login" route at all.
|
|
|
|
|
this.Io.use((socket: Socket, next) => {
|
|
|
|
|
//console.log(socket.handshake.query.token);
|
|
|
|
|
if (!socket.handshake.query || !socket.handshake.query.token) {
|
|
|
|
|
console.error('An authentication error happened, a user tried to connect without a token.');
|
|
|
|
|
return next(new Error('Authentication error'));
|
|
|
|
|
}
|
|
|
|
|
if(socket.handshake.query.token === 'test'){
|
|
|
|
|
if (ALLOW_ARTILLERY) {
|
|
|
|
|
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
|
|
|
|
(socket as ExSocketInterface).userId = this.nextUserId;
|
|
|
|
|
(socket as ExSocketInterface).userUuid = uuid();
|
|
|
|
|
this.nextUserId++;
|
|
|
|
|
(socket as ExSocketInterface).isArtillery = true;
|
|
|
|
|
console.log((socket as ExSocketInterface).userId);
|
|
|
|
|
next();
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
console.warn("In order to perform a load-testing test on this environment, you must set the ALLOW_ARTILLERY environment variable to 'true'");
|
|
|
|
|
next();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
(socket as ExSocketInterface).isArtillery = false;
|
|
|
|
|
if(this.searchClientByToken(socket.handshake.query.token)){
|
|
|
|
|
console.error('An authentication error happened, a user tried to connect while its token is already connected.');
|
|
|
|
|
return next(new Error('Authentication error'));
|
|
|
|
|
}
|
|
|
|
|
Jwt.verify(socket.handshake.query.token, SECRET_KEY, (err: JsonWebTokenError, tokenDecoded: object) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
console.error('An authentication error happened, invalid JsonWebToken.', err);
|
|
|
|
|
return next(new Error('Authentication error'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!this.isValidToken(tokenDecoded)) {
|
|
|
|
|
return next(new Error('Authentication error, invalid token structure'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
|
|
|
|
(socket as ExSocketInterface).userId = this.nextUserId;
|
|
|
|
|
(socket as ExSocketInterface).userUuid = tokenDecoded.userUuid;
|
|
|
|
|
this.nextUserId++;
|
|
|
|
|
next();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.ioConnection();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -167,201 +132,107 @@ export class IoSocketController {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ioConnection() {
|
|
|
|
|
this.Io.on(SocketIoEvent.CONNECTION, (socket: Socket) => {
|
|
|
|
|
const client : ExSocketInterface = socket as ExSocketInterface;
|
|
|
|
|
client.batchedMessages = new BatchMessage();
|
|
|
|
|
client.batchTimeout = null;
|
|
|
|
|
client.emitInBatch = (event: string, payload: SubMessage): void => {
|
|
|
|
|
emitInBatch(client, event, payload);
|
|
|
|
|
private authenticate(ws: WebSocket) {
|
|
|
|
|
//console.log(socket.handshake.query.token);
|
|
|
|
|
|
|
|
|
|
/*if (!socket.handshake.query || !socket.handshake.query.token) {
|
|
|
|
|
console.error('An authentication error happened, a user tried to connect without a token.');
|
|
|
|
|
return next(new Error('Authentication error'));
|
|
|
|
|
}
|
|
|
|
|
if(socket.handshake.query.token === 'test'){
|
|
|
|
|
if (ALLOW_ARTILLERY) {
|
|
|
|
|
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
|
|
|
|
(socket as ExSocketInterface).userId = this.nextUserId;
|
|
|
|
|
(socket as ExSocketInterface).userUuid = uuid();
|
|
|
|
|
this.nextUserId++;
|
|
|
|
|
(socket as ExSocketInterface).isArtillery = true;
|
|
|
|
|
console.log((socket as ExSocketInterface).userId);
|
|
|
|
|
next();
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
console.warn("In order to perform a load-testing test on this environment, you must set the ALLOW_ARTILLERY environment variable to 'true'");
|
|
|
|
|
next();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
(socket as ExSocketInterface).isArtillery = false;
|
|
|
|
|
if(this.searchClientByToken(socket.handshake.query.token)){
|
|
|
|
|
console.error('An authentication error happened, a user tried to connect while its token is already connected.');
|
|
|
|
|
return next(new Error('Authentication error'));
|
|
|
|
|
}
|
|
|
|
|
Jwt.verify(socket.handshake.query.token, SECRET_KEY, (err: JsonWebTokenError, tokenDecoded: object) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
console.error('An authentication error happened, invalid JsonWebToken.', err);
|
|
|
|
|
return next(new Error('Authentication error'));
|
|
|
|
|
}
|
|
|
|
|
this.sockets.set(client.userId, client);
|
|
|
|
|
|
|
|
|
|
// Let's log server load when a user joins
|
|
|
|
|
const srvSockets = this.Io.sockets.sockets;
|
|
|
|
|
this.nbClientsGauge.inc();
|
|
|
|
|
console.log(new Date().toISOString() + ' A user joined (', Object.keys(srvSockets).length, ' connected users)');
|
|
|
|
|
//si.currentLoad().then(data => console.log(' Current load: ', data.avgload));
|
|
|
|
|
//si.currentLoad().then(data => console.log(' CPU: ', data.currentload, '%'));
|
|
|
|
|
// End log server load
|
|
|
|
|
if (!this.isValidToken(tokenDecoded)) {
|
|
|
|
|
return next(new Error('Authentication error, invalid token structure'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*join-rom event permit to join one room.
|
|
|
|
|
message :
|
|
|
|
|
userId : user identification
|
|
|
|
|
roomId: room identification
|
|
|
|
|
position: position of user in map
|
|
|
|
|
x: user x position on map
|
|
|
|
|
y: user y position on map
|
|
|
|
|
*/
|
|
|
|
|
socket.on(SocketIoEvent.JOIN_ROOM, (message: unknown, answerFn): void => {
|
|
|
|
|
//console.log(SocketIoEvent.JOIN_ROOM, message);
|
|
|
|
|
try {
|
|
|
|
|
if (!isJoinRoomMessageInterface(message)) {
|
|
|
|
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid JOIN_ROOM message.'});
|
|
|
|
|
console.warn('Invalid JOIN_ROOM message received: ', message);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const roomId = message.roomId;
|
|
|
|
|
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
|
|
|
|
(socket as ExSocketInterface).userId = this.nextUserId;
|
|
|
|
|
(socket as ExSocketInterface).userUuid = tokenDecoded.userUuid;
|
|
|
|
|
this.nextUserId++;
|
|
|
|
|
next();
|
|
|
|
|
});*/
|
|
|
|
|
const socket = ws as ExSocketInterface;
|
|
|
|
|
socket.userId = this.nextUserId;
|
|
|
|
|
this.nextUserId++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Client = (socket as ExSocketInterface);
|
|
|
|
|
ioConnection() {
|
|
|
|
|
this.app.ws('/*', {
|
|
|
|
|
/* Options */
|
|
|
|
|
//compression: uWS.SHARED_COMPRESSOR,
|
|
|
|
|
maxPayloadLength: 16 * 1024 * 1024,
|
|
|
|
|
idleTimeout: 10,
|
|
|
|
|
/* Handlers */
|
|
|
|
|
open: (ws) => {
|
|
|
|
|
this.authenticate(ws);
|
|
|
|
|
// TODO: close if authenticate is ko
|
|
|
|
|
|
|
|
|
|
if (Client.roomId === roomId) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//leave previous room
|
|
|
|
|
this.leaveRoom(Client);
|
|
|
|
|
|
|
|
|
|
//join new previous room
|
|
|
|
|
const world = this.joinRoom(Client, roomId, message.position);
|
|
|
|
|
|
|
|
|
|
const things = world.setViewport(Client, message.viewport);
|
|
|
|
|
|
|
|
|
|
const listOfUsers: Array<MessageUserPosition> = [];
|
|
|
|
|
const listOfGroups: Array<GroupUpdateInterface> = [];
|
|
|
|
|
|
|
|
|
|
for (const thing of things) {
|
|
|
|
|
if (thing instanceof User) {
|
|
|
|
|
const player: ExSocketInterface|undefined = this.sockets.get(thing.id);
|
|
|
|
|
if (player === undefined) {
|
|
|
|
|
console.warn('Something went wrong. The World contains a user "'+thing.id+"' but this user does not exist in the sockets list!");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
listOfUsers.push(new MessageUserPosition(thing.id, player.name, player.characterLayers, player.position));
|
|
|
|
|
} else if (thing instanceof Group) {
|
|
|
|
|
listOfGroups.push({
|
|
|
|
|
groupId: thing.getId(),
|
|
|
|
|
position: thing.getPosition(),
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
console.error("Unexpected type for Movable returned by setViewport");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const listOfItems: {[itemId: string]: unknown} = {};
|
|
|
|
|
for (const [itemId, item] of world.getItemsState().entries()) {
|
|
|
|
|
listOfItems[itemId] = item;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//console.warn('ANSWER PLAYER POSITIONS', listOfUsers);
|
|
|
|
|
if (answerFn === undefined && ALLOW_ARTILLERY === true) {
|
|
|
|
|
// For some reason, answerFn can be undefined if we use Artillery (?)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
answerFn({
|
|
|
|
|
users: listOfUsers,
|
|
|
|
|
groups: listOfGroups,
|
|
|
|
|
items: listOfItems
|
|
|
|
|
});
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('An error occurred on "join_room" event');
|
|
|
|
|
console.error(e);
|
|
|
|
|
const client : ExSocketInterface = ws as ExSocketInterface;
|
|
|
|
|
client.batchedMessages = new BatchMessage();
|
|
|
|
|
client.batchTimeout = null;
|
|
|
|
|
client.emitInBatch = (payload: SubMessage): void => {
|
|
|
|
|
emitInBatch(client, payload);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
client.disconnecting = false;
|
|
|
|
|
this.sockets.set(client.userId, client);
|
|
|
|
|
|
|
|
|
|
socket.on(SocketIoEvent.SET_VIEWPORT, (message: unknown): void => {
|
|
|
|
|
try {
|
|
|
|
|
if (!(message instanceof Buffer)) {
|
|
|
|
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid SET_VIEWPORT message. Expecting binary buffer.'});
|
|
|
|
|
console.warn('Invalid SET_VIEWPORT message received (expecting binary buffer): ', message);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// Let's log server load when a user joins
|
|
|
|
|
this.nbClientsGauge.inc();
|
|
|
|
|
console.log(new Date().toISOString() + ' A user joined (', this.sockets.size, ' connected users)');
|
|
|
|
|
|
|
|
|
|
const viewportMessage = ViewportMessage.deserializeBinary(new Uint8Array(message as ArrayBuffer));
|
|
|
|
|
const viewport = viewportMessage.toObject();
|
|
|
|
|
},
|
|
|
|
|
message: (ws, arrayBuffer, isBinary) => {
|
|
|
|
|
const client = ws as ExSocketInterface;
|
|
|
|
|
const message = ClientToServerMessage.deserializeBinary(new Uint8Array(arrayBuffer));
|
|
|
|
|
|
|
|
|
|
const Client = (socket as ExSocketInterface);
|
|
|
|
|
Client.viewport = viewport;
|
|
|
|
|
|
|
|
|
|
const world = this.Worlds.get(Client.roomId);
|
|
|
|
|
if (!world) {
|
|
|
|
|
console.error("In SET_VIEWPORT, could not find world with id '", Client.roomId, "'");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
world.setViewport(Client, Client.viewport);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('An error occurred on "SET_VIEWPORT" event');
|
|
|
|
|
console.error(e);
|
|
|
|
|
if (message.hasJoinroommessage()) {
|
|
|
|
|
this.handleJoinRoom(client, message.getJoinroommessage() as JoinRoomMessage);
|
|
|
|
|
} else if (message.hasViewportmessage()) {
|
|
|
|
|
this.handleViewport(client, message.getViewportmessage() as ViewportMessage);
|
|
|
|
|
} else if (message.hasUsermovesmessage()) {
|
|
|
|
|
this.handleUserMovesMessage(client, message.getUsermovesmessage() as UserMovesMessage);
|
|
|
|
|
} else if (message.hasSetplayerdetailsmessage()) {
|
|
|
|
|
this.handleSetPlayerDetails(client, message.getSetplayerdetailsmessage() as SetPlayerDetailsMessage);
|
|
|
|
|
} else if (message.hasSilentmessage()) {
|
|
|
|
|
this.handleSilentMessage(client, message.getSilentmessage() as SilentMessage);
|
|
|
|
|
} else if (message.hasItemeventmessage()) {
|
|
|
|
|
this.handleItemEvent(client, message.getItemeventmessage() as ItemEventMessage);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
socket.on(SocketIoEvent.USER_POSITION, (message: unknown): void => {
|
|
|
|
|
//console.log(SockerIoEvent.USER_POSITION, userMovesMessage);
|
|
|
|
|
try {
|
|
|
|
|
if (!(message instanceof Buffer)) {
|
|
|
|
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid USER_POSITION message. Expecting binary buffer.'});
|
|
|
|
|
console.warn('Invalid USER_POSITION message received (expecting binary buffer): ', message);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const userMovesMessage = UserMovesMessage.deserializeBinary(new Uint8Array(message as ArrayBuffer));
|
|
|
|
|
const userMoves = userMovesMessage.toObject();
|
|
|
|
|
|
|
|
|
|
const position = userMoves.position;
|
|
|
|
|
if (position === undefined) {
|
|
|
|
|
throw new Error('Position not found in message');
|
|
|
|
|
}
|
|
|
|
|
const viewport = userMoves.viewport;
|
|
|
|
|
if (viewport === undefined) {
|
|
|
|
|
throw new Error('Viewport not found in message');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let direction: string;
|
|
|
|
|
switch (position.direction) {
|
|
|
|
|
case Direction.UP:
|
|
|
|
|
direction = 'up';
|
|
|
|
|
break;
|
|
|
|
|
case Direction.DOWN:
|
|
|
|
|
direction = 'down';
|
|
|
|
|
break;
|
|
|
|
|
case Direction.LEFT:
|
|
|
|
|
direction = 'left';
|
|
|
|
|
break;
|
|
|
|
|
case Direction.RIGHT:
|
|
|
|
|
direction = 'right';
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw new Error("Unexpected direction");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Client = (socket as ExSocketInterface);
|
|
|
|
|
|
|
|
|
|
// sending to all clients in room except sender
|
|
|
|
|
Client.position = {
|
|
|
|
|
x: position.x,
|
|
|
|
|
y: position.y,
|
|
|
|
|
direction,
|
|
|
|
|
moving: position.moving,
|
|
|
|
|
};
|
|
|
|
|
Client.viewport = viewport;
|
|
|
|
|
|
|
|
|
|
// update position in the world
|
|
|
|
|
const world = this.Worlds.get(Client.roomId);
|
|
|
|
|
if (!world) {
|
|
|
|
|
console.error("In USER_POSITION, could not find world with id '", Client.roomId, "'");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
world.updatePosition(Client, Client.position);
|
|
|
|
|
world.setViewport(Client, Client.viewport);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('An error occurred on "user_position" event');
|
|
|
|
|
console.error(e);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
socket.on(SocketIoEvent.WEBRTC_SIGNAL, (data: unknown) => {
|
|
|
|
|
this.emitVideo((socket as ExSocketInterface), data);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
socket.on(SocketIoEvent.WEBRTC_SCREEN_SHARING_SIGNAL, (data: unknown) => {
|
|
|
|
|
this.emitScreenSharing((socket as ExSocketInterface), data);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
socket.on(SocketIoEvent.DISCONNECT, () => {
|
|
|
|
|
const Client = (socket as ExSocketInterface);
|
|
|
|
|
/* Ok is false if backpressure was built up, wait for drain */
|
|
|
|
|
//let ok = ws.send(message, isBinary);
|
|
|
|
|
},
|
|
|
|
|
drain: (ws) => {
|
|
|
|
|
console.log('WebSocket backpressure: ' + ws.getBufferedAmount());
|
|
|
|
|
},
|
|
|
|
|
close: (ws, code, message) => {
|
|
|
|
|
const Client = (ws as ExSocketInterface);
|
|
|
|
|
try {
|
|
|
|
|
Client.disconnecting = true;
|
|
|
|
|
//leave room
|
|
|
|
|
this.leaveRoom(Client);
|
|
|
|
|
|
|
|
|
@@ -377,112 +248,251 @@ export class IoSocketController {
|
|
|
|
|
console.error('An error occurred on "disconnect"');
|
|
|
|
|
console.error(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.sockets.delete(Client.userId);
|
|
|
|
|
|
|
|
|
|
// Let's log server load when a user leaves
|
|
|
|
|
const srvSockets = this.Io.sockets.sockets;
|
|
|
|
|
this.nbClientsGauge.dec();
|
|
|
|
|
console.log('A user left (', Object.keys(srvSockets).length, ' connected users)');
|
|
|
|
|
//si.currentLoad().then(data => console.log('Current load: ', data.avgload));
|
|
|
|
|
//si.currentLoad().then(data => console.log('CPU: ', data.currentload, '%'));
|
|
|
|
|
// End log server load
|
|
|
|
|
console.log('A user left (', this.sockets.size, ' connected users)');
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// TODO: finish this!
|
|
|
|
|
/*this.Io.on(SocketIoEvent.CONNECTION, (socket: Socket) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
socket.on(SocketIoEvent.WEBRTC_SIGNAL, (data: unknown) => {
|
|
|
|
|
this.emitVideo((socket as ExSocketInterface), data);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Let's send the user id to the user
|
|
|
|
|
socket.on(SocketIoEvent.SET_PLAYER_DETAILS, (message: unknown, answerFn) => {
|
|
|
|
|
//console.log(SocketIoEvent.SET_PLAYER_DETAILS, message);
|
|
|
|
|
if (!(message instanceof Buffer)) {
|
|
|
|
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid SET_PLAYER_DETAILS message. Expecting binary buffer.'});
|
|
|
|
|
console.warn('Invalid SET_PLAYER_DETAILS message received (expecting binary buffer): ', message);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const playerDetailsMessage = SetPlayerDetailsMessage.deserializeBinary(new Uint8Array(message));
|
|
|
|
|
const playerDetails = {
|
|
|
|
|
name: playerDetailsMessage.getName(),
|
|
|
|
|
characterLayers: playerDetailsMessage.getCharacterlayersList()
|
|
|
|
|
};
|
|
|
|
|
//console.log(SocketIoEvent.SET_PLAYER_DETAILS, playerDetails);
|
|
|
|
|
if (!isSetPlayerDetailsMessage(playerDetails)) {
|
|
|
|
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid SET_PLAYER_DETAILS message.'});
|
|
|
|
|
console.warn('Invalid SET_PLAYER_DETAILS message received: ', playerDetails);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const Client = (socket as ExSocketInterface);
|
|
|
|
|
Client.name = playerDetails.name;
|
|
|
|
|
Client.characterLayers = playerDetails.characterLayers;
|
|
|
|
|
// Artillery fails when receiving an acknowledgement that is not a JSON object
|
|
|
|
|
if (!Client.isArtillery) {
|
|
|
|
|
answerFn(Client.userId);
|
|
|
|
|
}
|
|
|
|
|
socket.on(SocketIoEvent.WEBRTC_SCREEN_SHARING_SIGNAL, (data: unknown) => {
|
|
|
|
|
this.emitScreenSharing((socket as ExSocketInterface), data);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
socket.on(SocketIoEvent.SET_SILENT, (silent: unknown) => {
|
|
|
|
|
//console.log(SocketIoEvent.SET_SILENT, silent);
|
|
|
|
|
if (typeof silent !== "boolean") {
|
|
|
|
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid SET_SILENT message.'});
|
|
|
|
|
console.warn('Invalid SET_SILENT message received: ', silent);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
});*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const Client = (socket as ExSocketInterface);
|
|
|
|
|
private emitError(Client: ExSocketInterface, message: string): void {
|
|
|
|
|
const errorMessage = new ErrorMessage();
|
|
|
|
|
errorMessage.setMessage(message);
|
|
|
|
|
|
|
|
|
|
// update position in the world
|
|
|
|
|
const world = this.Worlds.get(Client.roomId);
|
|
|
|
|
if (!world) {
|
|
|
|
|
console.error("In SET_SILENT, could not find world with id '", Client.roomId, "'");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
world.setSilent(Client, silent);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('An error occurred on "SET_SILENT"');
|
|
|
|
|
console.error(e);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
const serverToClientMessage = new ServerToClientMessage();
|
|
|
|
|
serverToClientMessage.setErrormessage(errorMessage);
|
|
|
|
|
|
|
|
|
|
socket.on(SocketIoEvent.ITEM_EVENT, (message: unknown) => {
|
|
|
|
|
if (!(message instanceof Buffer)) {
|
|
|
|
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid ITEM_EVENT message. Expecting binary buffer.'});
|
|
|
|
|
console.warn('Invalid ITEM_EVENT message received (expecting binary buffer): ', message);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const itemEventMessage = ItemEventMessage.deserializeBinary(new Uint8Array(message));
|
|
|
|
|
if (!Client.disconnecting) {
|
|
|
|
|
Client.send(serverToClientMessage.serializeBinary().buffer);
|
|
|
|
|
}
|
|
|
|
|
console.warn(message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const itemEvent = ProtobufUtils.toItemEvent(itemEventMessage);
|
|
|
|
|
private handleJoinRoom(Client: ExSocketInterface, message: JoinRoomMessage): void {
|
|
|
|
|
try {
|
|
|
|
|
/*if (!isJoinRoomMessageInterface(message.toObject())) {
|
|
|
|
|
console.log(message.toObject())
|
|
|
|
|
this.emitError(Client, 'Invalid JOIN_ROOM message received: ' + message.toObject().toString());
|
|
|
|
|
return;
|
|
|
|
|
}*/
|
|
|
|
|
const roomId = message.getRoomid();
|
|
|
|
|
|
|
|
|
|
/*if (!isItemEventMessageInterface(itemEvent)) {
|
|
|
|
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid ITEM_EVENT message.'});
|
|
|
|
|
console.warn('Invalid ITEM_EVENT message received: ', itemEvent);
|
|
|
|
|
return;
|
|
|
|
|
}*/
|
|
|
|
|
try {
|
|
|
|
|
const Client = (socket as ExSocketInterface);
|
|
|
|
|
if (Client.roomId === roomId) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//socket.to(Client.roomId).emit(SocketIoEvent.ITEM_EVENT, itemEvent);
|
|
|
|
|
//leave previous room
|
|
|
|
|
this.leaveRoom(Client);
|
|
|
|
|
|
|
|
|
|
const world = this.Worlds.get(Client.roomId);
|
|
|
|
|
if (!world) {
|
|
|
|
|
console.error("Could not find world with id '", Client.roomId, "'");
|
|
|
|
|
return;
|
|
|
|
|
//join new previous room
|
|
|
|
|
const world = this.joinRoom(Client, roomId, ProtobufUtils.toPointInterface(message.getPosition() as PositionMessage));
|
|
|
|
|
|
|
|
|
|
const things = world.setViewport(Client, (message.getViewport() as ViewportMessage).toObject());
|
|
|
|
|
|
|
|
|
|
const roomJoinedMessage = new RoomJoinedMessage();
|
|
|
|
|
|
|
|
|
|
for (const thing of things) {
|
|
|
|
|
if (thing instanceof User) {
|
|
|
|
|
const player: ExSocketInterface|undefined = this.sockets.get(thing.id);
|
|
|
|
|
if (player === undefined) {
|
|
|
|
|
console.warn('Something went wrong. The World contains a user "'+thing.id+"' but this user does not exist in the sockets list!");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const subMessage = new SubMessage();
|
|
|
|
|
subMessage.setItemeventmessage(itemEventMessage);
|
|
|
|
|
const userJoinedMessage = new UserJoinedMessage();
|
|
|
|
|
userJoinedMessage.setUserid(thing.id);
|
|
|
|
|
userJoinedMessage.setName(player.name);
|
|
|
|
|
userJoinedMessage.setCharacterlayersList(player.characterLayers);
|
|
|
|
|
userJoinedMessage.setPosition(ProtobufUtils.toPositionMessage(player.position));
|
|
|
|
|
|
|
|
|
|
// Let's send the event without using the SocketIO room.
|
|
|
|
|
for (const user of world.getUsers().values()) {
|
|
|
|
|
const client = this.searchClientByIdOrFail(user.id);
|
|
|
|
|
//client.emit(SocketIoEvent.ITEM_EVENT, itemEvent);
|
|
|
|
|
emitInBatch(client, SocketIoEvent.ITEM_EVENT, subMessage);
|
|
|
|
|
}
|
|
|
|
|
roomJoinedMessage.addUser(userJoinedMessage);
|
|
|
|
|
} else if (thing instanceof Group) {
|
|
|
|
|
const groupUpdateMessage = new GroupUpdateMessage();
|
|
|
|
|
groupUpdateMessage.setGroupid(thing.getId());
|
|
|
|
|
groupUpdateMessage.setPosition(ProtobufUtils.toPointMessage(thing.getPosition()));
|
|
|
|
|
|
|
|
|
|
world.setItemState(itemEvent.itemId, itemEvent.state);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('An error occurred on "item_event"');
|
|
|
|
|
console.error(e);
|
|
|
|
|
roomJoinedMessage.addGroup(groupUpdateMessage);
|
|
|
|
|
} else {
|
|
|
|
|
console.error("Unexpected type for Movable returned by setViewport");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const [itemId, item] of world.getItemsState().entries()) {
|
|
|
|
|
const itemStateMessage = new ItemStateMessage();
|
|
|
|
|
itemStateMessage.setItemid(itemId);
|
|
|
|
|
itemStateMessage.setStatejson(JSON.stringify(item));
|
|
|
|
|
|
|
|
|
|
roomJoinedMessage.addItem(itemStateMessage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const serverToClientMessage = new ServerToClientMessage();
|
|
|
|
|
serverToClientMessage.setRoomjoinedmessage(roomJoinedMessage);
|
|
|
|
|
|
|
|
|
|
if (!Client.disconnecting) {
|
|
|
|
|
Client.send(serverToClientMessage.serializeBinary().buffer, true);
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('An error occurred on "join_room" event');
|
|
|
|
|
console.error(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private handleViewport(client: ExSocketInterface, viewportMessage: ViewportMessage) {
|
|
|
|
|
try {
|
|
|
|
|
const viewport = viewportMessage.toObject();
|
|
|
|
|
|
|
|
|
|
client.viewport = viewport;
|
|
|
|
|
|
|
|
|
|
const world = this.Worlds.get(client.roomId);
|
|
|
|
|
if (!world) {
|
|
|
|
|
console.error("In SET_VIEWPORT, could not find world with id '", client.roomId, "'");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
world.setViewport(client, client.viewport);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('An error occurred on "SET_VIEWPORT" event');
|
|
|
|
|
console.error(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private handleUserMovesMessage(client: ExSocketInterface, userMovesMessage: UserMovesMessage) {
|
|
|
|
|
//console.log(SockerIoEvent.USER_POSITION, userMovesMessage);
|
|
|
|
|
try {
|
|
|
|
|
const userMoves = userMovesMessage.toObject();
|
|
|
|
|
|
|
|
|
|
const position = userMoves.position;
|
|
|
|
|
if (position === undefined) {
|
|
|
|
|
throw new Error('Position not found in message');
|
|
|
|
|
}
|
|
|
|
|
const viewport = userMoves.viewport;
|
|
|
|
|
if (viewport === undefined) {
|
|
|
|
|
throw new Error('Viewport not found in message');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let direction: string;
|
|
|
|
|
switch (position.direction) {
|
|
|
|
|
case Direction.UP:
|
|
|
|
|
direction = 'up';
|
|
|
|
|
break;
|
|
|
|
|
case Direction.DOWN:
|
|
|
|
|
direction = 'down';
|
|
|
|
|
break;
|
|
|
|
|
case Direction.LEFT:
|
|
|
|
|
direction = 'left';
|
|
|
|
|
break;
|
|
|
|
|
case Direction.RIGHT:
|
|
|
|
|
direction = 'right';
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw new Error("Unexpected direction");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sending to all clients in room except sender
|
|
|
|
|
client.position = {
|
|
|
|
|
x: position.x,
|
|
|
|
|
y: position.y,
|
|
|
|
|
direction,
|
|
|
|
|
moving: position.moving,
|
|
|
|
|
};
|
|
|
|
|
client.viewport = viewport;
|
|
|
|
|
|
|
|
|
|
// update position in the world
|
|
|
|
|
const world = this.Worlds.get(client.roomId);
|
|
|
|
|
if (!world) {
|
|
|
|
|
console.error("In USER_POSITION, could not find world with id '", client.roomId, "'");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
world.updatePosition(client, client.position);
|
|
|
|
|
world.setViewport(client, client.viewport);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('An error occurred on "user_position" event');
|
|
|
|
|
console.error(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private handleSetPlayerDetails(client: ExSocketInterface, playerDetailsMessage: SetPlayerDetailsMessage) {
|
|
|
|
|
const playerDetails = {
|
|
|
|
|
name: playerDetailsMessage.getName(),
|
|
|
|
|
characterLayers: playerDetailsMessage.getCharacterlayersList()
|
|
|
|
|
};
|
|
|
|
|
//console.log(SocketIoEvent.SET_PLAYER_DETAILS, playerDetails);
|
|
|
|
|
if (!isSetPlayerDetailsMessage(playerDetails)) {
|
|
|
|
|
this.emitError(client, 'Invalid SET_PLAYER_DETAILS message received: ');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
client.name = playerDetails.name;
|
|
|
|
|
client.characterLayers = playerDetails.characterLayers;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const setUserIdMessage = new SetUserIdMessage();
|
|
|
|
|
setUserIdMessage.setUserid(client.userId);
|
|
|
|
|
|
|
|
|
|
const serverToClientMessage = new ServerToClientMessage();
|
|
|
|
|
serverToClientMessage.setSetuseridmessage(setUserIdMessage);
|
|
|
|
|
|
|
|
|
|
if (!client.disconnecting) {
|
|
|
|
|
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private handleSilentMessage(client: ExSocketInterface, silentMessage: SilentMessage) {
|
|
|
|
|
try {
|
|
|
|
|
// update position in the world
|
|
|
|
|
const world = this.Worlds.get(client.roomId);
|
|
|
|
|
if (!world) {
|
|
|
|
|
console.error("In handleSilentMessage, could not find world with id '", client.roomId, "'");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
world.setSilent(client, silentMessage.getSilent());
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('An error occurred on "handleSilentMessage"');
|
|
|
|
|
console.error(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private handleItemEvent(ws: ExSocketInterface, itemEventMessage: ItemEventMessage) {
|
|
|
|
|
const itemEvent = ProtobufUtils.toItemEvent(itemEventMessage);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const world = this.Worlds.get(ws.roomId);
|
|
|
|
|
if (!world) {
|
|
|
|
|
console.error("Could not find world with id '", ws.roomId, "'");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const subMessage = new SubMessage();
|
|
|
|
|
subMessage.setItemeventmessage(itemEventMessage);
|
|
|
|
|
|
|
|
|
|
// Let's send the event without using the SocketIO room.
|
|
|
|
|
for (const user of world.getUsers().values()) {
|
|
|
|
|
const client = this.searchClientByIdOrFail(user.id);
|
|
|
|
|
//client.emit(SocketIoEvent.ITEM_EVENT, itemEvent);
|
|
|
|
|
emitInBatch(client, subMessage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
world.setItemState(itemEvent.itemId, itemEvent.state);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('An error occurred on "item_event"');
|
|
|
|
|
console.error(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
emitVideo(socket: ExSocketInterface, data: unknown){
|
|
|
|
@@ -542,7 +552,7 @@ export class IoSocketController {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//user leave previous room
|
|
|
|
|
Client.leave(Client.roomId);
|
|
|
|
|
//Client.leave(Client.roomId);
|
|
|
|
|
} finally {
|
|
|
|
|
this.nbClientsPerRoomGauge.dec({ room: Client.roomId });
|
|
|
|
|
delete Client.roomId;
|
|
|
|
@@ -552,7 +562,7 @@ export class IoSocketController {
|
|
|
|
|
|
|
|
|
|
private joinRoom(Client : ExSocketInterface, roomId: string, position: PointInterface): World {
|
|
|
|
|
//join user in room
|
|
|
|
|
Client.join(roomId);
|
|
|
|
|
//Client.join(roomId);
|
|
|
|
|
this.nbClientsPerRoomGauge.inc({ room: roomId });
|
|
|
|
|
Client.roomId = roomId;
|
|
|
|
|
Client.position = position;
|
|
|
|
@@ -570,6 +580,9 @@ export class IoSocketController {
|
|
|
|
|
const clientUser = this.searchClientByIdOrFail(thing.id);
|
|
|
|
|
|
|
|
|
|
const userJoinedMessage = new UserJoinedMessage();
|
|
|
|
|
if (!Number.isInteger(clientUser.userId)) {
|
|
|
|
|
throw new Error('clientUser.userId is not an integer '+clientUser.userId);
|
|
|
|
|
}
|
|
|
|
|
userJoinedMessage.setUserid(clientUser.userId);
|
|
|
|
|
userJoinedMessage.setName(clientUser.name);
|
|
|
|
|
userJoinedMessage.setCharacterlayersList(clientUser.characterLayers);
|
|
|
|
@@ -578,7 +591,7 @@ export class IoSocketController {
|
|
|
|
|
const subMessage = new SubMessage();
|
|
|
|
|
subMessage.setUserjoinedmessage(userJoinedMessage);
|
|
|
|
|
|
|
|
|
|
emitInBatch(clientListener, SocketIoEvent.JOIN_ROOM, subMessage);
|
|
|
|
|
emitInBatch(clientListener, subMessage);
|
|
|
|
|
} else if (thing instanceof Group) {
|
|
|
|
|
this.emitCreateUpdateGroupEvent(clientListener, thing);
|
|
|
|
|
} else {
|
|
|
|
@@ -596,7 +609,7 @@ export class IoSocketController {
|
|
|
|
|
const subMessage = new SubMessage();
|
|
|
|
|
subMessage.setUsermovedmessage(userMovedMessage);
|
|
|
|
|
|
|
|
|
|
clientListener.emitInBatch(SocketIoEvent.USER_MOVED, subMessage);
|
|
|
|
|
clientListener.emitInBatch(subMessage);
|
|
|
|
|
//console.log("Sending USER_MOVED event");
|
|
|
|
|
} else if (thing instanceof Group) {
|
|
|
|
|
this.emitCreateUpdateGroupEvent(clientListener, thing);
|
|
|
|
@@ -627,7 +640,7 @@ export class IoSocketController {
|
|
|
|
|
return world;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private emitCreateUpdateGroupEvent(socket: Socket, group: Group): void {
|
|
|
|
|
private emitCreateUpdateGroupEvent(client: ExSocketInterface, group: Group): void {
|
|
|
|
|
const position = group.getPosition();
|
|
|
|
|
const pointMessage = new PointMessage();
|
|
|
|
|
pointMessage.setX(Math.floor(position.x));
|
|
|
|
@@ -639,8 +652,7 @@ export class IoSocketController {
|
|
|
|
|
const subMessage = new SubMessage();
|
|
|
|
|
subMessage.setGroupupdatemessage(groupUpdateMessage);
|
|
|
|
|
|
|
|
|
|
const client : ExSocketInterface = socket as ExSocketInterface;
|
|
|
|
|
emitInBatch(client, SocketIoEvent.GROUP_CREATE_UPDATE, subMessage);
|
|
|
|
|
emitInBatch(client, subMessage);
|
|
|
|
|
//socket.emit(SocketIoEvent.GROUP_CREATE_UPDATE, groupUpdateMessage.serializeBinary().buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -652,7 +664,7 @@ export class IoSocketController {
|
|
|
|
|
subMessage.setGroupdeletemessage(groupDeleteMessage);
|
|
|
|
|
|
|
|
|
|
const client : ExSocketInterface = socket as ExSocketInterface;
|
|
|
|
|
emitInBatch(client, SocketIoEvent.GROUP_DELETE, subMessage);
|
|
|
|
|
emitInBatch(client, subMessage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private emitUserLeftEvent(socket: Socket, userId: number): void {
|
|
|
|
@@ -663,7 +675,7 @@ export class IoSocketController {
|
|
|
|
|
subMessage.setUserleftmessage(userLeftMessage);
|
|
|
|
|
|
|
|
|
|
const client : ExSocketInterface = socket as ExSocketInterface;
|
|
|
|
|
emitInBatch(client, SocketIoEvent.USER_LEFT, subMessage);
|
|
|
|
|
emitInBatch(client, subMessage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@@ -672,6 +684,10 @@ export class IoSocketController {
|
|
|
|
|
* @param roomId
|
|
|
|
|
*/
|
|
|
|
|
joinWebRtcRoom(socket: ExSocketInterface, roomId: string) {
|
|
|
|
|
|
|
|
|
|
// TODO: REBUILD THIS
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (socket.webRtcRoomId === roomId) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@@ -734,6 +750,9 @@ export class IoSocketController {
|
|
|
|
|
|
|
|
|
|
//disconnect user
|
|
|
|
|
disConnectedUser(userId: number, group: Group) {
|
|
|
|
|
// TODO: rebuild this
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const Client = this.searchClientByIdOrFail(userId);
|
|
|
|
|
Client.to("webrtcroom"+group.getId()).emit(SocketIoEvent.WEBRTC_DISCONNECT, {
|
|
|
|
|
userId: userId
|
|
|
|
@@ -761,4 +780,5 @@ export class IoSocketController {
|
|
|
|
|
public getWorlds(): Map<string, World> {
|
|
|
|
|
return this.Worlds;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|