Migrating userId to "int32" to save some space and adding userMoves message in protobuf
This commit is contained in:
parent
4b55b54a07
commit
e9ca8721a6
@ -6,7 +6,7 @@ import { uuid } from 'uuidv4';
|
|||||||
|
|
||||||
export interface TokenInterface {
|
export interface TokenInterface {
|
||||||
name: string,
|
name: string,
|
||||||
userId: string
|
userUuid: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AuthenticateController {
|
export class AuthenticateController {
|
||||||
@ -28,12 +28,12 @@ export class AuthenticateController {
|
|||||||
});
|
});
|
||||||
}*/
|
}*/
|
||||||
//TODO check user email for The Coding Machine game
|
//TODO check user email for The Coding Machine game
|
||||||
const userId = uuid();
|
const userUuid = uuid();
|
||||||
const token = Jwt.sign({name: param.name, userId: userId} as TokenInterface, SECRET_KEY, {expiresIn: '24h'});
|
const token = Jwt.sign({name: param.name, userUuid: userUuid} as TokenInterface, SECRET_KEY, {expiresIn: '24h'});
|
||||||
return res.status(OK).send({
|
return res.status(OK).send({
|
||||||
token: token,
|
token: token,
|
||||||
mapUrlStart: URL_ROOM_STARTED,
|
mapUrlStart: URL_ROOM_STARTED,
|
||||||
userId: userId,
|
userId: userUuid,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,14 @@ import {isWebRtcSignalMessageInterface} from "../Model/Websocket/WebRtcSignalMes
|
|||||||
import {UserInGroupInterface} from "../Model/Websocket/UserInGroupInterface";
|
import {UserInGroupInterface} from "../Model/Websocket/UserInGroupInterface";
|
||||||
import {isItemEventMessageInterface} from "../Model/Websocket/ItemEventMessage";
|
import {isItemEventMessageInterface} from "../Model/Websocket/ItemEventMessage";
|
||||||
import {uuid} from 'uuidv4';
|
import {uuid} from 'uuidv4';
|
||||||
import {isUserMovesInterface} from "../Model/Websocket/UserMovesMessage";
|
|
||||||
import {isViewport} from "../Model/Websocket/ViewportMessage";
|
import {isViewport} from "../Model/Websocket/ViewportMessage";
|
||||||
import {GroupUpdateInterface} from "_Model/Websocket/GroupUpdateInterface";
|
import {GroupUpdateInterface} from "_Model/Websocket/GroupUpdateInterface";
|
||||||
import {Movable} from "../Model/Movable";
|
import {Movable} from "../Model/Movable";
|
||||||
import {SetPlayerDetailsMessage} from "../../../messages/generated/src/proto/messages_pb";
|
import {PositionMessage, SetPlayerDetailsMessage} from "../../../messages/generated/messages_pb";
|
||||||
|
import {UserMovesMessage} from "../../../messages/generated/messages_pb";
|
||||||
|
import Direction = PositionMessage.Direction;
|
||||||
|
|
||||||
enum SockerIoEvent {
|
enum SocketIoEvent {
|
||||||
CONNECTION = "connection",
|
CONNECTION = "connection",
|
||||||
DISCONNECT = "disconnect",
|
DISCONNECT = "disconnect",
|
||||||
JOIN_ROOM = "join-room", // bi-directional
|
JOIN_ROOM = "join-room", // bi-directional
|
||||||
@ -52,7 +53,7 @@ function emitInBatch(socket: ExSocketInterface, event: string | symbol, payload:
|
|||||||
|
|
||||||
if (socket.batchTimeout === null) {
|
if (socket.batchTimeout === null) {
|
||||||
socket.batchTimeout = setTimeout(() => {
|
socket.batchTimeout = setTimeout(() => {
|
||||||
socket.emit(SockerIoEvent.BATCH, socket.batchedMessages);
|
socket.emit(SocketIoEvent.BATCH, socket.batchedMessages);
|
||||||
socket.batchedMessages = [];
|
socket.batchedMessages = [];
|
||||||
socket.batchTimeout = null;
|
socket.batchTimeout = null;
|
||||||
}, 100);
|
}, 100);
|
||||||
@ -62,9 +63,10 @@ function emitInBatch(socket: ExSocketInterface, event: string | symbol, payload:
|
|||||||
export class IoSocketController {
|
export class IoSocketController {
|
||||||
public readonly Io: socketIO.Server;
|
public readonly Io: socketIO.Server;
|
||||||
private Worlds: Map<string, World> = new Map<string, World>();
|
private Worlds: Map<string, World> = new Map<string, World>();
|
||||||
private sockets: Map<string, ExSocketInterface> = new Map<string, ExSocketInterface>();
|
private sockets: Map<number, ExSocketInterface> = new Map<number, ExSocketInterface>();
|
||||||
private nbClientsGauge: Gauge<string>;
|
private nbClientsGauge: Gauge<string>;
|
||||||
private nbClientsPerRoomGauge: Gauge<string>;
|
private nbClientsPerRoomGauge: Gauge<string>;
|
||||||
|
private nextUserId: number = 1;
|
||||||
|
|
||||||
constructor(server: http.Server) {
|
constructor(server: http.Server) {
|
||||||
this.Io = socketIO(server);
|
this.Io = socketIO(server);
|
||||||
@ -90,7 +92,9 @@ export class IoSocketController {
|
|||||||
if(socket.handshake.query.token === 'test'){
|
if(socket.handshake.query.token === 'test'){
|
||||||
if (ALLOW_ARTILLERY) {
|
if (ALLOW_ARTILLERY) {
|
||||||
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
||||||
(socket as ExSocketInterface).userId = uuid();
|
(socket as ExSocketInterface).userId = this.nextUserId;
|
||||||
|
(socket as ExSocketInterface).userUuid = uuid();
|
||||||
|
this.nextUserId++;
|
||||||
(socket as ExSocketInterface).isArtillery = true;
|
(socket as ExSocketInterface).isArtillery = true;
|
||||||
console.log((socket as ExSocketInterface).userId);
|
console.log((socket as ExSocketInterface).userId);
|
||||||
next();
|
next();
|
||||||
@ -116,7 +120,9 @@ export class IoSocketController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
||||||
(socket as ExSocketInterface).userId = tokenDecoded.userId;
|
(socket as ExSocketInterface).userId = this.nextUserId;
|
||||||
|
(socket as ExSocketInterface).userUuid = tokenDecoded.userUuid;
|
||||||
|
this.nextUserId++;
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -125,7 +131,7 @@ export class IoSocketController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private isValidToken(token: object): token is TokenInterface {
|
private isValidToken(token: object): token is TokenInterface {
|
||||||
if (typeof((token as TokenInterface).userId) !== 'string') {
|
if (typeof((token as TokenInterface).userUuid) !== 'string') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (typeof((token as TokenInterface).name) !== 'string') {
|
if (typeof((token as TokenInterface).name) !== 'string') {
|
||||||
@ -151,7 +157,7 @@ export class IoSocketController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ioConnection() {
|
ioConnection() {
|
||||||
this.Io.on(SockerIoEvent.CONNECTION, (socket: Socket) => {
|
this.Io.on(SocketIoEvent.CONNECTION, (socket: Socket) => {
|
||||||
const client : ExSocketInterface = socket as ExSocketInterface;
|
const client : ExSocketInterface = socket as ExSocketInterface;
|
||||||
client.batchedMessages = [];
|
client.batchedMessages = [];
|
||||||
client.batchTimeout = null;
|
client.batchTimeout = null;
|
||||||
@ -176,11 +182,11 @@ export class IoSocketController {
|
|||||||
x: user x position on map
|
x: user x position on map
|
||||||
y: user y position on map
|
y: user y position on map
|
||||||
*/
|
*/
|
||||||
socket.on(SockerIoEvent.JOIN_ROOM, (message: unknown, answerFn): void => {
|
socket.on(SocketIoEvent.JOIN_ROOM, (message: unknown, answerFn): void => {
|
||||||
console.log(SockerIoEvent.JOIN_ROOM, message);
|
console.log(SocketIoEvent.JOIN_ROOM, message);
|
||||||
try {
|
try {
|
||||||
if (!isJoinRoomMessageInterface(message)) {
|
if (!isJoinRoomMessageInterface(message)) {
|
||||||
socket.emit(SockerIoEvent.MESSAGE_ERROR, {message: 'Invalid JOIN_ROOM message.'});
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid JOIN_ROOM message.'});
|
||||||
console.warn('Invalid JOIN_ROOM message received: ', message);
|
console.warn('Invalid JOIN_ROOM message received: ', message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -244,11 +250,11 @@ export class IoSocketController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on(SockerIoEvent.SET_VIEWPORT, (message: unknown): void => {
|
socket.on(SocketIoEvent.SET_VIEWPORT, (message: unknown): void => {
|
||||||
try {
|
try {
|
||||||
//console.log('SET_VIEWPORT')
|
//console.log('SET_VIEWPORT')
|
||||||
if (!isViewport(message)) {
|
if (!isViewport(message)) {
|
||||||
socket.emit(SockerIoEvent.MESSAGE_ERROR, {message: 'Invalid SET_VIEWPORT message.'});
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid SET_VIEWPORT message.'});
|
||||||
console.warn('Invalid SET_VIEWPORT message received: ', message);
|
console.warn('Invalid SET_VIEWPORT message received: ', message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -268,20 +274,47 @@ export class IoSocketController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on(SockerIoEvent.USER_POSITION, (userMovesMessage: unknown): void => {
|
socket.on(SocketIoEvent.USER_POSITION, (message: unknown): void => {
|
||||||
//console.log(SockerIoEvent.USER_POSITION, userMovesMessage);
|
//console.log(SockerIoEvent.USER_POSITION, userMovesMessage);
|
||||||
try {
|
try {
|
||||||
if (!isUserMovesInterface(userMovesMessage)) {
|
const userMovesMessage = UserMovesMessage.deserializeBinary(new Uint8Array(message as ArrayBuffer));
|
||||||
socket.emit(SockerIoEvent.MESSAGE_ERROR, {message: 'Invalid USER_POSITION message.'});
|
const userMoves = userMovesMessage.toObject();
|
||||||
console.warn('Invalid USER_POSITION message received: ', userMovesMessage);
|
|
||||||
return;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Client = (socket as ExSocketInterface);
|
const Client = (socket as ExSocketInterface);
|
||||||
|
|
||||||
// sending to all clients in room except sender
|
// sending to all clients in room except sender
|
||||||
Client.position = userMovesMessage.position;
|
Client.position = {
|
||||||
Client.viewport = userMovesMessage.viewport;
|
x: position.x,
|
||||||
|
y: position.y,
|
||||||
|
direction,
|
||||||
|
moving: position.moving,
|
||||||
|
};
|
||||||
|
Client.viewport = viewport;
|
||||||
|
|
||||||
// update position in the world
|
// update position in the world
|
||||||
const world = this.Worlds.get(Client.roomId);
|
const world = this.Worlds.get(Client.roomId);
|
||||||
@ -297,15 +330,15 @@ export class IoSocketController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on(SockerIoEvent.WEBRTC_SIGNAL, (data: unknown) => {
|
socket.on(SocketIoEvent.WEBRTC_SIGNAL, (data: unknown) => {
|
||||||
this.emitVideo((socket as ExSocketInterface), data);
|
this.emitVideo((socket as ExSocketInterface), data);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on(SockerIoEvent.WEBRTC_SCREEN_SHARING_SIGNAL, (data: unknown) => {
|
socket.on(SocketIoEvent.WEBRTC_SCREEN_SHARING_SIGNAL, (data: unknown) => {
|
||||||
this.emitScreenSharing((socket as ExSocketInterface), data);
|
this.emitScreenSharing((socket as ExSocketInterface), data);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on(SockerIoEvent.DISCONNECT, () => {
|
socket.on(SocketIoEvent.DISCONNECT, () => {
|
||||||
const Client = (socket as ExSocketInterface);
|
const Client = (socket as ExSocketInterface);
|
||||||
try {
|
try {
|
||||||
//leave room
|
//leave room
|
||||||
@ -335,16 +368,16 @@ export class IoSocketController {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Let's send the user id to the user
|
// Let's send the user id to the user
|
||||||
socket.on(SockerIoEvent.SET_PLAYER_DETAILS, (message: any, answerFn) => {
|
socket.on(SocketIoEvent.SET_PLAYER_DETAILS, (message: any, answerFn) => {
|
||||||
console.log(SockerIoEvent.SET_PLAYER_DETAILS, message);
|
console.log(SocketIoEvent.SET_PLAYER_DETAILS, message);
|
||||||
const playerDetailsMessage = SetPlayerDetailsMessage.deserializeBinary(new Uint8Array(message));
|
const playerDetailsMessage = SetPlayerDetailsMessage.deserializeBinary(new Uint8Array(message));
|
||||||
const playerDetails = {
|
const playerDetails = {
|
||||||
name: playerDetailsMessage.getName(),
|
name: playerDetailsMessage.getName(),
|
||||||
characterLayers: playerDetailsMessage.getCharacterlayersList()
|
characterLayers: playerDetailsMessage.getCharacterlayersList()
|
||||||
};
|
};
|
||||||
console.log(SockerIoEvent.SET_PLAYER_DETAILS, playerDetails);
|
console.log(SocketIoEvent.SET_PLAYER_DETAILS, playerDetails);
|
||||||
if (!isSetPlayerDetailsMessage(playerDetails)) {
|
if (!isSetPlayerDetailsMessage(playerDetails)) {
|
||||||
socket.emit(SockerIoEvent.MESSAGE_ERROR, {message: 'Invalid SET_PLAYER_DETAILS message.'});
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid SET_PLAYER_DETAILS message.'});
|
||||||
console.warn('Invalid SET_PLAYER_DETAILS message received: ', playerDetails);
|
console.warn('Invalid SET_PLAYER_DETAILS message received: ', playerDetails);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -357,10 +390,10 @@ export class IoSocketController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on(SockerIoEvent.SET_SILENT, (silent: unknown) => {
|
socket.on(SocketIoEvent.SET_SILENT, (silent: unknown) => {
|
||||||
console.log(SockerIoEvent.SET_SILENT, silent);
|
console.log(SocketIoEvent.SET_SILENT, silent);
|
||||||
if (typeof silent !== "boolean") {
|
if (typeof silent !== "boolean") {
|
||||||
socket.emit(SockerIoEvent.MESSAGE_ERROR, {message: 'Invalid SET_SILENT message.'});
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid SET_SILENT message.'});
|
||||||
console.warn('Invalid SET_SILENT message received: ', silent);
|
console.warn('Invalid SET_SILENT message received: ', silent);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -381,16 +414,16 @@ export class IoSocketController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on(SockerIoEvent.ITEM_EVENT, (itemEvent: unknown) => {
|
socket.on(SocketIoEvent.ITEM_EVENT, (itemEvent: unknown) => {
|
||||||
if (!isItemEventMessageInterface(itemEvent)) {
|
if (!isItemEventMessageInterface(itemEvent)) {
|
||||||
socket.emit(SockerIoEvent.MESSAGE_ERROR, {message: 'Invalid ITEM_EVENT message.'});
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid ITEM_EVENT message.'});
|
||||||
console.warn('Invalid ITEM_EVENT message received: ', itemEvent);
|
console.warn('Invalid ITEM_EVENT message received: ', itemEvent);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const Client = (socket as ExSocketInterface);
|
const Client = (socket as ExSocketInterface);
|
||||||
|
|
||||||
socket.to(Client.roomId).emit(SockerIoEvent.ITEM_EVENT, itemEvent);
|
socket.to(Client.roomId).emit(SocketIoEvent.ITEM_EVENT, itemEvent);
|
||||||
|
|
||||||
const world = this.Worlds.get(Client.roomId);
|
const world = this.Worlds.get(Client.roomId);
|
||||||
if (!world) {
|
if (!world) {
|
||||||
@ -408,7 +441,7 @@ export class IoSocketController {
|
|||||||
|
|
||||||
emitVideo(socket: ExSocketInterface, data: unknown){
|
emitVideo(socket: ExSocketInterface, data: unknown){
|
||||||
if (!isWebRtcSignalMessageInterface(data)) {
|
if (!isWebRtcSignalMessageInterface(data)) {
|
||||||
socket.emit(SockerIoEvent.MESSAGE_ERROR, {message: 'Invalid WEBRTC_SIGNAL message.'});
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid WEBRTC_SIGNAL message.'});
|
||||||
console.warn('Invalid WEBRTC_SIGNAL message received: ', data);
|
console.warn('Invalid WEBRTC_SIGNAL message received: ', data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -418,7 +451,7 @@ export class IoSocketController {
|
|||||||
console.warn("While exchanging a WebRTC signal: client with id ", data.receiverId, " does not exist. This might be a race condition.");
|
console.warn("While exchanging a WebRTC signal: client with id ", data.receiverId, " does not exist. This might be a race condition.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return client.emit(SockerIoEvent.WEBRTC_SIGNAL, {
|
return client.emit(SocketIoEvent.WEBRTC_SIGNAL, {
|
||||||
userId: socket.userId,
|
userId: socket.userId,
|
||||||
signal: data.signal
|
signal: data.signal
|
||||||
});
|
});
|
||||||
@ -426,7 +459,7 @@ export class IoSocketController {
|
|||||||
|
|
||||||
emitScreenSharing(socket: ExSocketInterface, data: unknown){
|
emitScreenSharing(socket: ExSocketInterface, data: unknown){
|
||||||
if (!isWebRtcSignalMessageInterface(data)) {
|
if (!isWebRtcSignalMessageInterface(data)) {
|
||||||
socket.emit(SockerIoEvent.MESSAGE_ERROR, {message: 'Invalid WEBRTC_SCREEN_SHARING message.'});
|
socket.emit(SocketIoEvent.MESSAGE_ERROR, {message: 'Invalid WEBRTC_SCREEN_SHARING message.'});
|
||||||
console.warn('Invalid WEBRTC_SCREEN_SHARING message received: ', data);
|
console.warn('Invalid WEBRTC_SCREEN_SHARING message received: ', data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -436,13 +469,13 @@ export class IoSocketController {
|
|||||||
console.warn("While exchanging a WEBRTC_SCREEN_SHARING signal: client with id ", data.receiverId, " does not exist. This might be a race condition.");
|
console.warn("While exchanging a WEBRTC_SCREEN_SHARING signal: client with id ", data.receiverId, " does not exist. This might be a race condition.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return client.emit(SockerIoEvent.WEBRTC_SCREEN_SHARING_SIGNAL, {
|
return client.emit(SocketIoEvent.WEBRTC_SCREEN_SHARING_SIGNAL, {
|
||||||
userId: socket.userId,
|
userId: socket.userId,
|
||||||
signal: data.signal
|
signal: data.signal
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
searchClientByIdOrFail(userId: string): ExSocketInterface {
|
searchClientByIdOrFail(userId: number): ExSocketInterface {
|
||||||
const client: ExSocketInterface|undefined = this.sockets.get(userId);
|
const client: ExSocketInterface|undefined = this.sockets.get(userId);
|
||||||
if (client === undefined) {
|
if (client === undefined) {
|
||||||
throw new Error("Could not find user with id " + userId);
|
throw new Error("Could not find user with id " + userId);
|
||||||
@ -481,9 +514,9 @@ export class IoSocketController {
|
|||||||
//check and create new world for a room
|
//check and create new world for a room
|
||||||
let world = this.Worlds.get(roomId)
|
let world = this.Worlds.get(roomId)
|
||||||
if(world === undefined){
|
if(world === undefined){
|
||||||
world = new World((user1: string, group: Group) => {
|
world = new World((user1: number, group: Group) => {
|
||||||
this.connectedUser(user1, group);
|
this.connectedUser(user1, group);
|
||||||
}, (user1: string, group: Group) => {
|
}, (user1: number, group: Group) => {
|
||||||
this.disConnectedUser(user1, group);
|
this.disConnectedUser(user1, group);
|
||||||
}, MINIMUM_DISTANCE, GROUP_RADIUS, (thing: Movable, listener: User) => {
|
}, MINIMUM_DISTANCE, GROUP_RADIUS, (thing: Movable, listener: User) => {
|
||||||
const clientListener = this.searchClientByIdOrFail(listener.id);
|
const clientListener = this.searchClientByIdOrFail(listener.id);
|
||||||
@ -491,9 +524,9 @@ export class IoSocketController {
|
|||||||
const clientUser = this.searchClientByIdOrFail(thing.id);
|
const clientUser = this.searchClientByIdOrFail(thing.id);
|
||||||
const messageUserJoined = new MessageUserJoined(clientUser.userId, clientUser.name, clientUser.characterLayers, clientUser.position);
|
const messageUserJoined = new MessageUserJoined(clientUser.userId, clientUser.name, clientUser.characterLayers, clientUser.position);
|
||||||
|
|
||||||
clientListener.emit(SockerIoEvent.JOIN_ROOM, messageUserJoined);
|
clientListener.emit(SocketIoEvent.JOIN_ROOM, messageUserJoined);
|
||||||
} else if (thing instanceof Group) {
|
} else if (thing instanceof Group) {
|
||||||
clientListener.emit(SockerIoEvent.GROUP_CREATE_UPDATE, {
|
clientListener.emit(SocketIoEvent.GROUP_CREATE_UPDATE, {
|
||||||
position: thing.getPosition(),
|
position: thing.getPosition(),
|
||||||
groupId: thing.getId()
|
groupId: thing.getId()
|
||||||
} as GroupUpdateInterface);
|
} as GroupUpdateInterface);
|
||||||
@ -505,10 +538,10 @@ export class IoSocketController {
|
|||||||
if (thing instanceof User) {
|
if (thing instanceof User) {
|
||||||
const clientUser = this.searchClientByIdOrFail(thing.id);
|
const clientUser = this.searchClientByIdOrFail(thing.id);
|
||||||
|
|
||||||
clientListener.emitInBatch(SockerIoEvent.USER_MOVED, new MessageUserMoved(clientUser.userId, clientUser.position));
|
clientListener.emitInBatch(SocketIoEvent.USER_MOVED, new MessageUserMoved(clientUser.userId, clientUser.position));
|
||||||
//console.log("Sending USER_MOVED event");
|
//console.log("Sending USER_MOVED event");
|
||||||
} else if (thing instanceof Group) {
|
} else if (thing instanceof Group) {
|
||||||
clientListener.emit(SockerIoEvent.GROUP_CREATE_UPDATE, {
|
clientListener.emit(SocketIoEvent.GROUP_CREATE_UPDATE, {
|
||||||
position: thing.getPosition(),
|
position: thing.getPosition(),
|
||||||
groupId: thing.getId()
|
groupId: thing.getId()
|
||||||
} as GroupUpdateInterface);
|
} as GroupUpdateInterface);
|
||||||
@ -519,10 +552,10 @@ export class IoSocketController {
|
|||||||
const clientListener = this.searchClientByIdOrFail(listener.id);
|
const clientListener = this.searchClientByIdOrFail(listener.id);
|
||||||
if (thing instanceof User) {
|
if (thing instanceof User) {
|
||||||
const clientUser = this.searchClientByIdOrFail(thing.id);
|
const clientUser = this.searchClientByIdOrFail(thing.id);
|
||||||
clientListener.emit(SockerIoEvent.USER_LEFT, clientUser.userId);
|
clientListener.emit(SocketIoEvent.USER_LEFT, clientUser.userId);
|
||||||
//console.log("Sending USER_LEFT event");
|
//console.log("Sending USER_LEFT event");
|
||||||
} else if (thing instanceof Group) {
|
} else if (thing instanceof Group) {
|
||||||
clientListener.emit(SockerIoEvent.GROUP_DELETE, thing.getId());
|
clientListener.emit(SocketIoEvent.GROUP_DELETE, thing.getId());
|
||||||
} else {
|
} else {
|
||||||
console.error('Unexpected type for Movable.');
|
console.error('Unexpected type for Movable.');
|
||||||
}
|
}
|
||||||
@ -533,7 +566,7 @@ export class IoSocketController {
|
|||||||
|
|
||||||
// Dispatch groups position to newly connected user
|
// Dispatch groups position to newly connected user
|
||||||
world.getGroups().forEach((group: Group) => {
|
world.getGroups().forEach((group: Group) => {
|
||||||
Client.emit(SockerIoEvent.GROUP_CREATE_UPDATE, {
|
Client.emit(SocketIoEvent.GROUP_CREATE_UPDATE, {
|
||||||
position: group.getPosition(),
|
position: group.getPosition(),
|
||||||
groupId: group.getId()
|
groupId: group.getId()
|
||||||
} as GroupUpdateInterface);
|
} as GroupUpdateInterface);
|
||||||
@ -578,7 +611,7 @@ export class IoSocketController {
|
|||||||
return tabs;
|
return tabs;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
client.emit(SockerIoEvent.WEBRTC_START, {clients: peerClients, roomId: roomId});
|
client.emit(SocketIoEvent.WEBRTC_START, {clients: peerClients, roomId: roomId});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,19 +633,19 @@ export class IoSocketController {
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
//connected user
|
//connected user
|
||||||
connectedUser(userId: string, group: Group) {
|
connectedUser(userId: number, group: Group) {
|
||||||
/*let Client = this.sockets.get(userId);
|
/*let Client = this.sockets.get(userId);
|
||||||
if (Client === undefined) {
|
if (Client === undefined) {
|
||||||
return;
|
return;
|
||||||
}*/
|
}*/
|
||||||
const Client = this.searchClientByIdOrFail(userId);
|
const Client = this.searchClientByIdOrFail(userId);
|
||||||
this.joinWebRtcRoom(Client, group.getId());
|
this.joinWebRtcRoom(Client, "webrtcroom"+group.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
//disconnect user
|
//disconnect user
|
||||||
disConnectedUser(userId: string, group: Group) {
|
disConnectedUser(userId: number, group: Group) {
|
||||||
const Client = this.searchClientByIdOrFail(userId);
|
const Client = this.searchClientByIdOrFail(userId);
|
||||||
Client.to(group.getId()).emit(SockerIoEvent.WEBRTC_DISCONNECT, {
|
Client.to("webrtcroom"+group.getId()).emit(SocketIoEvent.WEBRTC_DISCONNECT, {
|
||||||
userId: userId
|
userId: userId
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -622,7 +655,7 @@ export class IoSocketController {
|
|||||||
// the other player will try connecting until a timeout happens (during this time, the connection icon will be displayed for nothing).
|
// the other player will try connecting until a timeout happens (during this time, the connection icon will be displayed for nothing).
|
||||||
// So we also send the disconnect event to the other player.
|
// So we also send the disconnect event to the other player.
|
||||||
for (const user of group.getUsers()) {
|
for (const user of group.getUsers()) {
|
||||||
Client.emit(SockerIoEvent.WEBRTC_DISCONNECT, {
|
Client.emit(SocketIoEvent.WEBRTC_DISCONNECT, {
|
||||||
userId: user.id
|
userId: user.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,9 @@ import {Movable} from "_Model/Movable";
|
|||||||
export class Group implements Movable {
|
export class Group implements Movable {
|
||||||
static readonly MAX_PER_GROUP = 4;
|
static readonly MAX_PER_GROUP = 4;
|
||||||
|
|
||||||
private id: string;
|
private static nextId: number = 1;
|
||||||
|
|
||||||
|
private id: number;
|
||||||
private users: Set<User>;
|
private users: Set<User>;
|
||||||
private connectCallback: ConnectCallback;
|
private connectCallback: ConnectCallback;
|
||||||
private disconnectCallback: DisconnectCallback;
|
private disconnectCallback: DisconnectCallback;
|
||||||
@ -17,7 +19,8 @@ export class Group implements Movable {
|
|||||||
this.users = new Set<User>();
|
this.users = new Set<User>();
|
||||||
this.connectCallback = connectCallback;
|
this.connectCallback = connectCallback;
|
||||||
this.disconnectCallback = disconnectCallback;
|
this.disconnectCallback = disconnectCallback;
|
||||||
this.id = uuid();
|
this.id = Group.nextId;
|
||||||
|
Group.nextId++;
|
||||||
|
|
||||||
users.forEach((user: User) => {
|
users.forEach((user: User) => {
|
||||||
this.join(user);
|
this.join(user);
|
||||||
@ -28,7 +31,7 @@ export class Group implements Movable {
|
|||||||
return Array.from(this.users.values());
|
return Array.from(this.users.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
getId() : string{
|
getId() : number {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ export class User implements Movable {
|
|||||||
public group?: Group;
|
public group?: Group;
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
public id: string,
|
public id: number,
|
||||||
public position: PointInterface,
|
public position: PointInterface,
|
||||||
public silent: boolean,
|
public silent: boolean,
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@ export interface ExSocketInterface extends Socket, Identificable {
|
|||||||
token: string;
|
token: string;
|
||||||
roomId: string;
|
roomId: string;
|
||||||
webRtcRoomId: string;
|
webRtcRoomId: string;
|
||||||
userId: string;
|
userId: number; // A temporary (autoincremented) identifier for this user
|
||||||
|
userUuid: string; // A unique identifier for this user
|
||||||
name: string;
|
name: string;
|
||||||
characterLayers: string[];
|
characterLayers: string[];
|
||||||
position: PointInterface;
|
position: PointInterface;
|
||||||
|
@ -2,5 +2,5 @@ import {PositionInterface} from "_Model/PositionInterface";
|
|||||||
|
|
||||||
export interface GroupUpdateInterface {
|
export interface GroupUpdateInterface {
|
||||||
position: PositionInterface,
|
position: PositionInterface,
|
||||||
groupId: string,
|
groupId: number,
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export interface Identificable {
|
export interface Identificable {
|
||||||
userId: string;
|
userId: number;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {PointInterface} from "_Model/Websocket/PointInterface";
|
import {PointInterface} from "_Model/Websocket/PointInterface";
|
||||||
|
|
||||||
export class MessageUserJoined {
|
export class MessageUserJoined {
|
||||||
constructor(public userId: string, public name: string, public characterLayers: string[], public position: PointInterface) {
|
constructor(public userId: number, public name: string, public characterLayers: string[], public position: PointInterface) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {PointInterface} from "./PointInterface";
|
import {PointInterface} from "./PointInterface";
|
||||||
|
|
||||||
export class MessageUserMoved {
|
export class MessageUserMoved {
|
||||||
constructor(public userId: string, public position: PointInterface) {
|
constructor(public userId: number, public position: PointInterface) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,6 @@ export class Point implements PointInterface{
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class MessageUserPosition {
|
export class MessageUserPosition {
|
||||||
constructor(public userId: string, public name: string, public characterLayers: string[], public position: PointInterface) {
|
constructor(public userId: number, public name: string, public characterLayers: string[], public position: PointInterface) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export interface UserInGroupInterface {
|
export interface UserInGroupInterface {
|
||||||
userId: string,
|
userId: number,
|
||||||
name: string,
|
name: string,
|
||||||
initiator: boolean
|
initiator: boolean
|
||||||
}
|
}
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
import * as tg from "generic-type-guard";
|
|
||||||
import {isPointInterface} from "./PointInterface";
|
|
||||||
import {isViewport} from "./ViewportMessage";
|
|
||||||
|
|
||||||
|
|
||||||
export const isUserMovesInterface =
|
|
||||||
new tg.IsInterface().withProperties({
|
|
||||||
position: isPointInterface,
|
|
||||||
viewport: isViewport,
|
|
||||||
}).get();
|
|
||||||
export type UserMovesInterface = tg.GuardedType<typeof isUserMovesInterface>;
|
|
@ -7,12 +7,12 @@ export const isSignalData =
|
|||||||
|
|
||||||
export const isWebRtcSignalMessageInterface =
|
export const isWebRtcSignalMessageInterface =
|
||||||
new tg.IsInterface().withProperties({
|
new tg.IsInterface().withProperties({
|
||||||
receiverId: tg.isString,
|
receiverId: tg.isNumber,
|
||||||
signal: isSignalData
|
signal: isSignalData
|
||||||
}).get();
|
}).get();
|
||||||
export const isWebRtcScreenSharingStartMessageInterface =
|
export const isWebRtcScreenSharingStartMessageInterface =
|
||||||
new tg.IsInterface().withProperties({
|
new tg.IsInterface().withProperties({
|
||||||
userId: tg.isString,
|
userId: tg.isNumber,
|
||||||
roomId: tg.isString
|
roomId: tg.isString
|
||||||
}).get();
|
}).get();
|
||||||
export type WebRtcSignalMessageInterface = tg.GuardedType<typeof isWebRtcSignalMessageInterface>;
|
export type WebRtcSignalMessageInterface = tg.GuardedType<typeof isWebRtcSignalMessageInterface>;
|
||||||
|
@ -11,15 +11,15 @@ import {PositionNotifier} from "./PositionNotifier";
|
|||||||
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
|
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
|
||||||
import {Movable} from "_Model/Movable";
|
import {Movable} from "_Model/Movable";
|
||||||
|
|
||||||
export type ConnectCallback = (user: string, group: Group) => void;
|
export type ConnectCallback = (user: number, group: Group) => void;
|
||||||
export type DisconnectCallback = (user: string, group: Group) => void;
|
export type DisconnectCallback = (user: number, group: Group) => void;
|
||||||
|
|
||||||
export class World {
|
export class World {
|
||||||
private readonly minDistance: number;
|
private readonly minDistance: number;
|
||||||
private readonly groupRadius: number;
|
private readonly groupRadius: number;
|
||||||
|
|
||||||
// Users, sorted by ID
|
// Users, sorted by ID
|
||||||
private readonly users: Map<string, User>;
|
private readonly users: Map<number, User>;
|
||||||
private readonly groups: Set<Group>;
|
private readonly groups: Set<Group>;
|
||||||
|
|
||||||
private readonly connectCallback: ConnectCallback;
|
private readonly connectCallback: ConnectCallback;
|
||||||
@ -37,7 +37,7 @@ export class World {
|
|||||||
onMoves: MovesCallback,
|
onMoves: MovesCallback,
|
||||||
onLeaves: LeavesCallback)
|
onLeaves: LeavesCallback)
|
||||||
{
|
{
|
||||||
this.users = new Map<string, User>();
|
this.users = new Map<number, User>();
|
||||||
this.groups = new Set<Group>();
|
this.groups = new Set<Group>();
|
||||||
this.connectCallback = connectCallback;
|
this.connectCallback = connectCallback;
|
||||||
this.disconnectCallback = disconnectCallback;
|
this.disconnectCallback = disconnectCallback;
|
||||||
@ -51,7 +51,7 @@ export class World {
|
|||||||
return Array.from(this.groups.values());
|
return Array.from(this.groups.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
public getUsers(): Map<string, User> {
|
public getUsers(): Map<number, User> {
|
||||||
return this.users;
|
return this.users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,14 +32,14 @@ describe("PositionNotifier", () => {
|
|||||||
leaveTriggered = true;
|
leaveTriggered = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
const user1 = new User("1", {
|
const user1 = new User(1, {
|
||||||
x: 500,
|
x: 500,
|
||||||
y: 500,
|
y: 500,
|
||||||
moving: false,
|
moving: false,
|
||||||
direction: 'down'
|
direction: 'down'
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
const user2 = new User("2", {
|
const user2 = new User(2, {
|
||||||
x: -9999,
|
x: -9999,
|
||||||
y: -9999,
|
y: -9999,
|
||||||
moving: false,
|
moving: false,
|
||||||
@ -110,14 +110,14 @@ describe("PositionNotifier", () => {
|
|||||||
leaveTriggered = true;
|
leaveTriggered = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
const user1 = new User("1", {
|
const user1 = new User(1, {
|
||||||
x: 500,
|
x: 500,
|
||||||
y: 500,
|
y: 500,
|
||||||
moving: false,
|
moving: false,
|
||||||
direction: 'down'
|
direction: 'down'
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
const user2 = new User("2", {
|
const user2 = new User(2, {
|
||||||
x: -9999,
|
x: -9999,
|
||||||
y: -9999,
|
y: -9999,
|
||||||
moving: false,
|
moving: false,
|
||||||
|
@ -6,55 +6,55 @@ import { Group } from "../src/Model/Group";
|
|||||||
describe("World", () => {
|
describe("World", () => {
|
||||||
it("should connect user1 and user2", () => {
|
it("should connect user1 and user2", () => {
|
||||||
let connectCalledNumber: number = 0;
|
let connectCalledNumber: number = 0;
|
||||||
const connect: ConnectCallback = (user: string, group: Group): void => {
|
const connect: ConnectCallback = (user: number, group: Group): void => {
|
||||||
connectCalledNumber++;
|
connectCalledNumber++;
|
||||||
}
|
}
|
||||||
const disconnect: DisconnectCallback = (user: string, group: Group): void => {
|
const disconnect: DisconnectCallback = (user: number, group: Group): void => {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const world = new World(connect, disconnect, 160, 160, () => {}, () => {}, () => {});
|
const world = new World(connect, disconnect, 160, 160, () => {}, () => {}, () => {});
|
||||||
|
|
||||||
world.join({ userId: "foo" }, new Point(100, 100));
|
world.join({ userId: 1 }, new Point(100, 100));
|
||||||
|
|
||||||
world.join({ userId: "bar" }, new Point(500, 100));
|
world.join({ userId: 2 }, new Point(500, 100));
|
||||||
|
|
||||||
world.updatePosition({ userId: "bar" }, new Point(261, 100));
|
world.updatePosition({ userId: 2 }, new Point(261, 100));
|
||||||
|
|
||||||
expect(connectCalledNumber).toBe(0);
|
expect(connectCalledNumber).toBe(0);
|
||||||
|
|
||||||
world.updatePosition({ userId: "bar" }, new Point(101, 100));
|
world.updatePosition({ userId: 2 }, new Point(101, 100));
|
||||||
|
|
||||||
expect(connectCalledNumber).toBe(2);
|
expect(connectCalledNumber).toBe(2);
|
||||||
|
|
||||||
world.updatePosition({ userId: "bar" }, new Point(102, 100));
|
world.updatePosition({ userId: 2 }, new Point(102, 100));
|
||||||
expect(connectCalledNumber).toBe(2);
|
expect(connectCalledNumber).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should connect 3 users", () => {
|
it("should connect 3 users", () => {
|
||||||
let connectCalled: boolean = false;
|
let connectCalled: boolean = false;
|
||||||
const connect: ConnectCallback = (user: string, group: Group): void => {
|
const connect: ConnectCallback = (user: number, group: Group): void => {
|
||||||
connectCalled = true;
|
connectCalled = true;
|
||||||
}
|
}
|
||||||
const disconnect: DisconnectCallback = (user: string, group: Group): void => {
|
const disconnect: DisconnectCallback = (user: number, group: Group): void => {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const world = new World(connect, disconnect, 160, 160, () => {}, () => {}, () => {});
|
const world = new World(connect, disconnect, 160, 160, () => {}, () => {}, () => {});
|
||||||
|
|
||||||
world.join({ userId: "foo" }, new Point(100, 100));
|
world.join({ userId: 1 }, new Point(100, 100));
|
||||||
|
|
||||||
world.join({ userId: "bar" }, new Point(200, 100));
|
world.join({ userId: 2 }, new Point(200, 100));
|
||||||
|
|
||||||
expect(connectCalled).toBe(true);
|
expect(connectCalled).toBe(true);
|
||||||
connectCalled = false;
|
connectCalled = false;
|
||||||
|
|
||||||
// baz joins at the outer limit of the group
|
// baz joins at the outer limit of the group
|
||||||
world.join({ userId: "baz" }, new Point(311, 100));
|
world.join({ userId: 3 }, new Point(311, 100));
|
||||||
|
|
||||||
expect(connectCalled).toBe(false);
|
expect(connectCalled).toBe(false);
|
||||||
|
|
||||||
world.updatePosition({ userId: "baz" }, new Point(309, 100));
|
world.updatePosition({ userId: 3 }, new Point(309, 100));
|
||||||
|
|
||||||
expect(connectCalled).toBe(true);
|
expect(connectCalled).toBe(true);
|
||||||
});
|
});
|
||||||
@ -62,27 +62,27 @@ describe("World", () => {
|
|||||||
it("should disconnect user1 and user2", () => {
|
it("should disconnect user1 and user2", () => {
|
||||||
let connectCalled: boolean = false;
|
let connectCalled: boolean = false;
|
||||||
let disconnectCallNumber: number = 0;
|
let disconnectCallNumber: number = 0;
|
||||||
const connect: ConnectCallback = (user: string, group: Group): void => {
|
const connect: ConnectCallback = (user: number, group: Group): void => {
|
||||||
connectCalled = true;
|
connectCalled = true;
|
||||||
}
|
}
|
||||||
const disconnect: DisconnectCallback = (user: string, group: Group): void => {
|
const disconnect: DisconnectCallback = (user: number, group: Group): void => {
|
||||||
disconnectCallNumber++;
|
disconnectCallNumber++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const world = new World(connect, disconnect, 160, 160, () => {}, () => {}, () => {});
|
const world = new World(connect, disconnect, 160, 160, () => {}, () => {}, () => {});
|
||||||
|
|
||||||
world.join({ userId: "foo" }, new Point(100, 100));
|
world.join({ userId: 1 }, new Point(100, 100));
|
||||||
|
|
||||||
world.join({ userId: "bar" }, new Point(259, 100));
|
world.join({ userId: 2 }, new Point(259, 100));
|
||||||
|
|
||||||
expect(connectCalled).toBe(true);
|
expect(connectCalled).toBe(true);
|
||||||
expect(disconnectCallNumber).toBe(0);
|
expect(disconnectCallNumber).toBe(0);
|
||||||
|
|
||||||
world.updatePosition({ userId: "bar" }, new Point(100+160+160+1, 100));
|
world.updatePosition({ userId: 2 }, new Point(100+160+160+1, 100));
|
||||||
|
|
||||||
expect(disconnectCallNumber).toBe(2);
|
expect(disconnectCallNumber).toBe(2);
|
||||||
|
|
||||||
world.updatePosition({ userId: "bar" }, new Point(262, 100));
|
world.updatePosition({ userId: 2 }, new Point(262, 100));
|
||||||
expect(disconnectCallNumber).toBe(2);
|
expect(disconnectCallNumber).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ services:
|
|||||||
- "traefik.http.routers.maps-ssl.service=maps"
|
- "traefik.http.routers.maps-ssl.service=maps"
|
||||||
|
|
||||||
back:
|
back:
|
||||||
image: thecodingmachine/workadventure-back-base:latest
|
image: thecodingmachine/nodejs:12
|
||||||
command: yarn dev
|
command: yarn dev
|
||||||
#command: yarn run profile
|
#command: yarn run profile
|
||||||
environment:
|
environment:
|
||||||
@ -103,3 +103,11 @@ services:
|
|||||||
- "traefik.http.routers.website-ssl.entryPoints=websecure"
|
- "traefik.http.routers.website-ssl.entryPoints=websecure"
|
||||||
- "traefik.http.routers.website-ssl.tls=true"
|
- "traefik.http.routers.website-ssl.tls=true"
|
||||||
- "traefik.http.routers.website-ssl.service=website"
|
- "traefik.http.routers.website-ssl.service=website"
|
||||||
|
|
||||||
|
messages:
|
||||||
|
image: thecodingmachine/workadventure-back-base:latest
|
||||||
|
environment:
|
||||||
|
STARTUP_COMMAND_1: yarn install
|
||||||
|
STARTUP_COMMAND_2: yarn run proto:watch
|
||||||
|
volumes:
|
||||||
|
- ./messages:/usr/src/app
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
import Axios from "axios";
|
import Axios from "axios";
|
||||||
import {API_URL} from "./Enum/EnvironmentVariable";
|
import {API_URL} from "./Enum/EnvironmentVariable";
|
||||||
import {MessageUI} from "./Logger/MessageUI";
|
import {MessageUI} from "./Logger/MessageUI";
|
||||||
import {SetPlayerDetailsMessage} from "../../messages/generated/src/proto/messages_pb"
|
import {
|
||||||
|
PositionMessage,
|
||||||
|
SetPlayerDetailsMessage,
|
||||||
|
UserMovesMessage,
|
||||||
|
ViewportMessage
|
||||||
|
} from "../../messages/generated/messages_pb"
|
||||||
|
|
||||||
const SocketIo = require('socket.io-client');
|
const SocketIo = require('socket.io-client');
|
||||||
import Socket = SocketIOClient.Socket;
|
import Socket = SocketIOClient.Socket;
|
||||||
import {PlayerAnimationNames} from "./Phaser/Player/Animation";
|
import {PlayerAnimationNames} from "./Phaser/Player/Animation";
|
||||||
import {UserSimplePeerInterface} from "./WebRtc/SimplePeer";
|
import {UserSimplePeerInterface} from "./WebRtc/SimplePeer";
|
||||||
import {SignalData} from "simple-peer";
|
import {SignalData} from "simple-peer";
|
||||||
|
import Direction = PositionMessage.Direction;
|
||||||
|
|
||||||
enum EventMessage{
|
enum EventMessage{
|
||||||
WEBRTC_SIGNAL = "webrtc-signal",
|
WEBRTC_SIGNAL = "webrtc-signal",
|
||||||
@ -46,19 +52,19 @@ export class Point implements PointInterface{
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageUserPositionInterface {
|
export interface MessageUserPositionInterface {
|
||||||
userId: string;
|
userId: number;
|
||||||
name: string;
|
name: string;
|
||||||
characterLayers: string[];
|
characterLayers: string[];
|
||||||
position: PointInterface;
|
position: PointInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageUserMovedInterface {
|
export interface MessageUserMovedInterface {
|
||||||
userId: string;
|
userId: number;
|
||||||
position: PointInterface;
|
position: PointInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageUserJoined {
|
export interface MessageUserJoined {
|
||||||
userId: string;
|
userId: number;
|
||||||
name: string;
|
name: string;
|
||||||
characterLayers: string[];
|
characterLayers: string[];
|
||||||
position: PointInterface
|
position: PointInterface
|
||||||
@ -80,16 +86,16 @@ export interface WebRtcStartMessageInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface WebRtcDisconnectMessageInterface {
|
export interface WebRtcDisconnectMessageInterface {
|
||||||
userId: string
|
userId: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WebRtcSignalSentMessageInterface {
|
export interface WebRtcSignalSentMessageInterface {
|
||||||
receiverId: string,
|
receiverId: number,
|
||||||
signal: SignalData
|
signal: SignalData
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WebRtcSignalReceivedMessageInterface {
|
export interface WebRtcSignalReceivedMessageInterface {
|
||||||
userId: string,
|
userId: number,
|
||||||
signal: SignalData
|
signal: SignalData
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,11 +111,6 @@ export interface ViewportInterface {
|
|||||||
bottom: number,
|
bottom: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserMovesInterface {
|
|
||||||
position: PositionInterface,
|
|
||||||
viewport: ViewportInterface,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BatchedMessageInterface {
|
export interface BatchedMessageInterface {
|
||||||
event: string,
|
event: string,
|
||||||
payload: unknown
|
payload: unknown
|
||||||
@ -130,7 +131,7 @@ export interface RoomJoinedMessageInterface {
|
|||||||
|
|
||||||
export class Connection implements Connection {
|
export class Connection implements Connection {
|
||||||
private readonly socket: Socket;
|
private readonly socket: Socket;
|
||||||
private userId: string|null = null;
|
private userId: number|null = null;
|
||||||
|
|
||||||
private constructor(token: string) {
|
private constructor(token: string) {
|
||||||
|
|
||||||
@ -173,7 +174,7 @@ export class Connection implements Connection {
|
|||||||
const message = new SetPlayerDetailsMessage();
|
const message = new SetPlayerDetailsMessage();
|
||||||
message.setName(name);
|
message.setName(name);
|
||||||
message.setCharacterlayersList(characterLayersSelected);
|
message.setCharacterlayersList(characterLayersSelected);
|
||||||
connection.socket.emit(EventMessage.SET_PLAYER_DETAILS, message.serializeBinary().buffer, (id: string) => {
|
connection.socket.emit(EventMessage.SET_PLAYER_DETAILS, message.serializeBinary().buffer, (id: number) => {
|
||||||
connection.userId = id;
|
connection.userId = id;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -214,7 +215,40 @@ export class Connection implements Connection {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const point = new Point(x, y, direction, moving);
|
const point = new Point(x, y, direction, moving);
|
||||||
this.socket.emit(EventMessage.USER_POSITION, { position: point, viewport } as UserMovesInterface);
|
const positionMessage = new PositionMessage();
|
||||||
|
positionMessage.setX(Math.floor(x));
|
||||||
|
positionMessage.setY(Math.floor(y));
|
||||||
|
let directionEnum: PositionMessage.DirectionMap[keyof PositionMessage.DirectionMap];
|
||||||
|
switch (direction) {
|
||||||
|
case 'up':
|
||||||
|
directionEnum = Direction.UP;
|
||||||
|
break;
|
||||||
|
case 'down':
|
||||||
|
directionEnum = Direction.DOWN;
|
||||||
|
break;
|
||||||
|
case 'left':
|
||||||
|
directionEnum = Direction.LEFT;
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
directionEnum = Direction.RIGHT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("Unexpected direction");
|
||||||
|
}
|
||||||
|
positionMessage.setDirection(directionEnum);
|
||||||
|
positionMessage.setMoving(moving);
|
||||||
|
|
||||||
|
const viewportMessage = new ViewportMessage();
|
||||||
|
viewportMessage.setLeft(Math.floor(viewport.left));
|
||||||
|
viewportMessage.setRight(Math.floor(viewport.right));
|
||||||
|
viewportMessage.setTop(Math.floor(viewport.top));
|
||||||
|
viewportMessage.setBottom(Math.floor(viewport.bottom));
|
||||||
|
|
||||||
|
const userMovesMessage = new UserMovesMessage();
|
||||||
|
userMovesMessage.setPosition(positionMessage);
|
||||||
|
userMovesMessage.setViewport(viewportMessage);
|
||||||
|
|
||||||
|
this.socket.emit(EventMessage.USER_POSITION, userMovesMessage.serializeBinary().buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setSilent(silent: boolean): void {
|
public setSilent(silent: boolean): void {
|
||||||
@ -233,7 +267,7 @@ export class Connection implements Connection {
|
|||||||
this.socket.on(EventMessage.USER_MOVED, callback);
|
this.socket.on(EventMessage.USER_MOVED, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onUserLeft(callback: (userId: string) => void): void {
|
public onUserLeft(callback: (userId: number) => void): void {
|
||||||
this.socket.on(EventMessage.USER_LEFT, callback);
|
this.socket.on(EventMessage.USER_LEFT, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,14 +283,14 @@ export class Connection implements Connection {
|
|||||||
this.socket.on(EventMessage.CONNECT_ERROR, callback)
|
this.socket.on(EventMessage.CONNECT_ERROR, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
public sendWebrtcSignal(signal: unknown, receiverId : string) {
|
public sendWebrtcSignal(signal: unknown, receiverId: number) {
|
||||||
return this.socket.emit(EventMessage.WEBRTC_SIGNAL, {
|
return this.socket.emit(EventMessage.WEBRTC_SIGNAL, {
|
||||||
receiverId: receiverId,
|
receiverId: receiverId,
|
||||||
signal: signal
|
signal: signal
|
||||||
} as WebRtcSignalSentMessageInterface);
|
} as WebRtcSignalSentMessageInterface);
|
||||||
}
|
}
|
||||||
|
|
||||||
public sendWebrtcScreenSharingSignal(signal: unknown, receiverId : string) {
|
public sendWebrtcScreenSharingSignal(signal: unknown, receiverId: number) {
|
||||||
return this.socket.emit(EventMessage.WEBRTC_SCREEN_SHARING_SIGNAL, {
|
return this.socket.emit(EventMessage.WEBRTC_SCREEN_SHARING_SIGNAL, {
|
||||||
receiverId: receiverId,
|
receiverId: receiverId,
|
||||||
signal: signal
|
signal: signal
|
||||||
@ -286,7 +320,7 @@ export class Connection implements Connection {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getUserId(): string|null {
|
public getUserId(): number|null {
|
||||||
return this.userId;
|
return this.userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,10 +6,10 @@ import {Character} from "../Entity/Character";
|
|||||||
* Class representing the sprite of a remote player (a player that plays on another computer)
|
* Class representing the sprite of a remote player (a player that plays on another computer)
|
||||||
*/
|
*/
|
||||||
export class RemotePlayer extends Character {
|
export class RemotePlayer extends Character {
|
||||||
userId: string;
|
userId: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
userId: string,
|
userId: number,
|
||||||
Scene: GameScene,
|
Scene: GameScene,
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import {PointInterface} from "../../Connection";
|
import {PointInterface} from "../../Connection";
|
||||||
|
|
||||||
export interface AddPlayerInterface {
|
export interface AddPlayerInterface {
|
||||||
userId: string;
|
userId: number;
|
||||||
name: string;
|
name: string;
|
||||||
characterLayers: string[];
|
characterLayers: string[];
|
||||||
position: PointInterface;
|
position: PointInterface;
|
||||||
|
@ -63,7 +63,7 @@ interface AddPlayerEventInterface {
|
|||||||
|
|
||||||
interface RemovePlayerEventInterface {
|
interface RemovePlayerEventInterface {
|
||||||
type: 'RemovePlayerEvent'
|
type: 'RemovePlayerEvent'
|
||||||
userId: string
|
userId: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserMovedEventInterface {
|
interface UserMovedEventInterface {
|
||||||
@ -86,7 +86,7 @@ export class GameScene extends Phaser.Scene implements CenterListener {
|
|||||||
Terrains : Array<Phaser.Tilemaps.Tileset>;
|
Terrains : Array<Phaser.Tilemaps.Tileset>;
|
||||||
CurrentPlayer!: CurrentGamerInterface;
|
CurrentPlayer!: CurrentGamerInterface;
|
||||||
MapPlayers!: Phaser.Physics.Arcade.Group;
|
MapPlayers!: Phaser.Physics.Arcade.Group;
|
||||||
MapPlayersByKey : Map<string, RemotePlayer> = new Map<string, RemotePlayer>();
|
MapPlayersByKey : Map<number, RemotePlayer> = new Map<number, RemotePlayer>();
|
||||||
Map!: Phaser.Tilemaps.Tilemap;
|
Map!: Phaser.Tilemaps.Tilemap;
|
||||||
Layers!: Array<Phaser.Tilemaps.StaticTilemapLayer>;
|
Layers!: Array<Phaser.Tilemaps.StaticTilemapLayer>;
|
||||||
Objects!: Array<Phaser.Physics.Arcade.Sprite>;
|
Objects!: Array<Phaser.Physics.Arcade.Sprite>;
|
||||||
@ -217,7 +217,7 @@ export class GameScene extends Phaser.Scene implements CenterListener {
|
|||||||
this.updatePlayerPosition(message);
|
this.updatePlayerPosition(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.onUserLeft((userId: string) => {
|
connection.onUserLeft((userId: number) => {
|
||||||
this.removePlayer(userId);
|
this.removePlayer(userId);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -271,7 +271,7 @@ export class GameScene extends Phaser.Scene implements CenterListener {
|
|||||||
self.presentationModeSprite.setVisible(true);
|
self.presentationModeSprite.setVisible(true);
|
||||||
self.chatModeSprite.setVisible(true);
|
self.chatModeSprite.setVisible(true);
|
||||||
},
|
},
|
||||||
onDisconnect(userId: string) {
|
onDisconnect(userId: number) {
|
||||||
if (self.simplePeer.getNbConnections() === 0) {
|
if (self.simplePeer.getNbConnections() === 0) {
|
||||||
self.presentationModeSprite.setVisible(false);
|
self.presentationModeSprite.setVisible(false);
|
||||||
self.chatModeSprite.setVisible(false);
|
self.chatModeSprite.setVisible(false);
|
||||||
@ -918,7 +918,7 @@ export class GameScene extends Phaser.Scene implements CenterListener {
|
|||||||
|
|
||||||
// Let's move all users
|
// Let's move all users
|
||||||
const updatedPlayersPositions = this.playersPositionInterpolator.getUpdatedPositions(time);
|
const updatedPlayersPositions = this.playersPositionInterpolator.getUpdatedPositions(time);
|
||||||
updatedPlayersPositions.forEach((moveEvent: HasMovedEvent, userId: string) => {
|
updatedPlayersPositions.forEach((moveEvent: HasMovedEvent, userId: number) => {
|
||||||
const player : RemotePlayer | undefined = this.MapPlayersByKey.get(userId);
|
const player : RemotePlayer | undefined = this.MapPlayersByKey.get(userId);
|
||||||
if (player === undefined) {
|
if (player === undefined) {
|
||||||
throw new Error('Cannot find player with ID "' + userId +'"');
|
throw new Error('Cannot find player with ID "' + userId +'"');
|
||||||
@ -973,7 +973,7 @@ export class GameScene extends Phaser.Scene implements CenterListener {
|
|||||||
player.destroy();
|
player.destroy();
|
||||||
this.MapPlayers.remove(player);
|
this.MapPlayers.remove(player);
|
||||||
});
|
});
|
||||||
this.MapPlayersByKey = new Map<string, RemotePlayer>();
|
this.MapPlayersByKey = new Map<number, RemotePlayer>();
|
||||||
|
|
||||||
// load map
|
// load map
|
||||||
usersPosition.forEach((userPosition : MessageUserPositionInterface) => {
|
usersPosition.forEach((userPosition : MessageUserPositionInterface) => {
|
||||||
@ -1030,14 +1030,14 @@ export class GameScene extends Phaser.Scene implements CenterListener {
|
|||||||
/**
|
/**
|
||||||
* Called by the connexion when a player is removed from the map
|
* Called by the connexion when a player is removed from the map
|
||||||
*/
|
*/
|
||||||
public removePlayer(userId: string) {
|
public removePlayer(userId: number) {
|
||||||
this.pendingEvents.enqueue({
|
this.pendingEvents.enqueue({
|
||||||
type: "RemovePlayerEvent",
|
type: "RemovePlayerEvent",
|
||||||
userId
|
userId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private doRemovePlayer(userId: string) {
|
private doRemovePlayer(userId: number) {
|
||||||
const player = this.MapPlayersByKey.get(userId);
|
const player = this.MapPlayersByKey.get(userId);
|
||||||
if (player === undefined) {
|
if (player === undefined) {
|
||||||
console.error('Cannot find user with id ', userId);
|
console.error('Cannot find user with id ', userId);
|
||||||
|
@ -6,19 +6,19 @@ import {PlayerMovement} from "./PlayerMovement";
|
|||||||
import {HasMovedEvent} from "./GameManager";
|
import {HasMovedEvent} from "./GameManager";
|
||||||
|
|
||||||
export class PlayersPositionInterpolator {
|
export class PlayersPositionInterpolator {
|
||||||
playerMovements: Map<string, PlayerMovement> = new Map<string, PlayerMovement>();
|
playerMovements: Map<number, PlayerMovement> = new Map<number, PlayerMovement>();
|
||||||
|
|
||||||
updatePlayerPosition(userId: string, playerMovement: PlayerMovement) : void {
|
updatePlayerPosition(userId: number, playerMovement: PlayerMovement) : void {
|
||||||
this.playerMovements.set(userId, playerMovement);
|
this.playerMovements.set(userId, playerMovement);
|
||||||
}
|
}
|
||||||
|
|
||||||
removePlayer(userId: string): void {
|
removePlayer(userId: number): void {
|
||||||
this.playerMovements.delete(userId);
|
this.playerMovements.delete(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
getUpdatedPositions(tick: number) : Map<string, HasMovedEvent> {
|
getUpdatedPositions(tick: number) : Map<number, HasMovedEvent> {
|
||||||
const positions = new Map<string, HasMovedEvent>();
|
const positions = new Map<number, HasMovedEvent>();
|
||||||
this.playerMovements.forEach((playerMovement: PlayerMovement, userId: string) => {
|
this.playerMovements.forEach((playerMovement: PlayerMovement, userId: number) => {
|
||||||
if (playerMovement.isOutdated(tick)) {
|
if (playerMovement.isOutdated(tick)) {
|
||||||
//console.log("outdated")
|
//console.log("outdated")
|
||||||
this.playerMovements.delete(userId);
|
this.playerMovements.delete(userId);
|
||||||
|
@ -387,7 +387,7 @@ export class MediaManager {
|
|||||||
*
|
*
|
||||||
* @param userId
|
* @param userId
|
||||||
*/
|
*/
|
||||||
disabledMicrophoneByUserId(userId: string){
|
disabledMicrophoneByUserId(userId: number){
|
||||||
const element = document.getElementById(`microphone-${userId}`);
|
const element = document.getElementById(`microphone-${userId}`);
|
||||||
if(!element){
|
if(!element){
|
||||||
return;
|
return;
|
||||||
@ -399,7 +399,7 @@ export class MediaManager {
|
|||||||
*
|
*
|
||||||
* @param userId
|
* @param userId
|
||||||
*/
|
*/
|
||||||
enabledMicrophoneByUserId(userId: string){
|
enabledMicrophoneByUserId(userId: number){
|
||||||
const element = document.getElementById(`microphone-${userId}`);
|
const element = document.getElementById(`microphone-${userId}`);
|
||||||
if(!element){
|
if(!element){
|
||||||
return;
|
return;
|
||||||
@ -411,7 +411,7 @@ export class MediaManager {
|
|||||||
*
|
*
|
||||||
* @param userId
|
* @param userId
|
||||||
*/
|
*/
|
||||||
disabledVideoByUserId(userId: string) {
|
disabledVideoByUserId(userId: number) {
|
||||||
let element = document.getElementById(`${userId}`);
|
let element = document.getElementById(`${userId}`);
|
||||||
if (element) {
|
if (element) {
|
||||||
element.style.opacity = "0";
|
element.style.opacity = "0";
|
||||||
@ -426,7 +426,7 @@ export class MediaManager {
|
|||||||
*
|
*
|
||||||
* @param userId
|
* @param userId
|
||||||
*/
|
*/
|
||||||
enabledVideoByUserId(userId: string){
|
enabledVideoByUserId(userId: number){
|
||||||
let element = document.getElementById(`${userId}`);
|
let element = document.getElementById(`${userId}`);
|
||||||
if(element){
|
if(element){
|
||||||
element.style.opacity = "1";
|
element.style.opacity = "1";
|
||||||
|
@ -14,7 +14,7 @@ export class ScreenSharingPeer extends Peer {
|
|||||||
*/
|
*/
|
||||||
private isReceivingStream:boolean = false;
|
private isReceivingStream:boolean = false;
|
||||||
|
|
||||||
constructor(private userId: string, initiator: boolean, private connection: Connection) {
|
constructor(private userId: number, initiator: boolean, private connection: Connection) {
|
||||||
super({
|
super({
|
||||||
initiator: initiator ? initiator : false,
|
initiator: initiator ? initiator : false,
|
||||||
reconnectTimer: 10000,
|
reconnectTimer: 10000,
|
||||||
@ -52,7 +52,7 @@ export class ScreenSharingPeer extends Peer {
|
|||||||
if (message.streamEnded !== true) {
|
if (message.streamEnded !== true) {
|
||||||
console.error('Unexpected message on screen sharing peer connection');
|
console.error('Unexpected message on screen sharing peer connection');
|
||||||
}
|
}
|
||||||
mediaManager.removeActiveScreenSharingVideo(this.userId);
|
mediaManager.removeActiveScreenSharingVideo("" + this.userId);
|
||||||
});
|
});
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@ -63,7 +63,7 @@ export class ScreenSharingPeer extends Peer {
|
|||||||
|
|
||||||
this.on('connect', () => {
|
this.on('connect', () => {
|
||||||
// FIXME: we need to put the loader on the screen sharing connection
|
// FIXME: we need to put the loader on the screen sharing connection
|
||||||
mediaManager.isConnected(this.userId);
|
mediaManager.isConnected("" + this.userId);
|
||||||
console.info(`connect => ${this.userId}`);
|
console.info(`connect => ${this.userId}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -86,10 +86,10 @@ export class ScreenSharingPeer extends Peer {
|
|||||||
//console.log(`ScreenSharingPeer::stream => ${this.userId}`, stream);
|
//console.log(`ScreenSharingPeer::stream => ${this.userId}`, stream);
|
||||||
//console.log(`stream => ${this.userId} => `, stream);
|
//console.log(`stream => ${this.userId} => `, stream);
|
||||||
if(!stream){
|
if(!stream){
|
||||||
mediaManager.removeActiveScreenSharingVideo(this.userId);
|
mediaManager.removeActiveScreenSharingVideo("" + this.userId);
|
||||||
this.isReceivingStream = false;
|
this.isReceivingStream = false;
|
||||||
} else {
|
} else {
|
||||||
mediaManager.addStreamRemoteScreenSharing(this.userId, stream);
|
mediaManager.addStreamRemoteScreenSharing("" + this.userId, stream);
|
||||||
this.isReceivingStream = true;
|
this.isReceivingStream = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,7 +100,7 @@ export class ScreenSharingPeer extends Peer {
|
|||||||
|
|
||||||
public destroy(error?: Error): void {
|
public destroy(error?: Error): void {
|
||||||
try {
|
try {
|
||||||
mediaManager.removeActiveScreenSharingVideo(this.userId);
|
mediaManager.removeActiveScreenSharingVideo("" + this.userId);
|
||||||
// FIXME: I don't understand why "Closing connection with" message is displayed TWICE before "Nb users in peerConnectionArray"
|
// FIXME: I don't understand why "Closing connection with" message is displayed TWICE before "Nb users in peerConnectionArray"
|
||||||
// I do understand the method closeConnection is called twice, but I don't understand how they manage to run in parallel.
|
// I do understand the method closeConnection is called twice, but I don't understand how they manage to run in parallel.
|
||||||
//console.log('Closing connection with '+userId);
|
//console.log('Closing connection with '+userId);
|
||||||
|
@ -16,7 +16,7 @@ import {VideoPeer} from "./VideoPeer";
|
|||||||
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
||||||
|
|
||||||
export interface UserSimplePeerInterface{
|
export interface UserSimplePeerInterface{
|
||||||
userId: string;
|
userId: number;
|
||||||
name?: string;
|
name?: string;
|
||||||
initiator?: boolean;
|
initiator?: boolean;
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ export interface UserSimplePeerInterface{
|
|||||||
export interface PeerConnectionListener {
|
export interface PeerConnectionListener {
|
||||||
onConnect(user: UserSimplePeerInterface): void;
|
onConnect(user: UserSimplePeerInterface): void;
|
||||||
|
|
||||||
onDisconnect(userId: string): void;
|
onDisconnect(userId: number): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,8 +35,8 @@ export class SimplePeer {
|
|||||||
private WebRtcRoomId: string;
|
private WebRtcRoomId: string;
|
||||||
private Users: Array<UserSimplePeerInterface> = new Array<UserSimplePeerInterface>();
|
private Users: Array<UserSimplePeerInterface> = new Array<UserSimplePeerInterface>();
|
||||||
|
|
||||||
private PeerScreenSharingConnectionArray: Map<string, ScreenSharingPeer> = new Map<string, ScreenSharingPeer>();
|
private PeerScreenSharingConnectionArray: Map<number, ScreenSharingPeer> = new Map<number, ScreenSharingPeer>();
|
||||||
private PeerConnectionArray: Map<string, VideoPeer> = new Map<string, VideoPeer>();
|
private PeerConnectionArray: Map<number, VideoPeer> = new Map<number, VideoPeer>();
|
||||||
private readonly sendLocalVideoStreamCallback: UpdatedLocalStreamCallback;
|
private readonly sendLocalVideoStreamCallback: UpdatedLocalStreamCallback;
|
||||||
private readonly sendLocalScreenSharingStreamCallback: StartScreenSharingCallback;
|
private readonly sendLocalScreenSharingStreamCallback: StartScreenSharingCallback;
|
||||||
private readonly stopLocalScreenSharingStreamCallback: StopScreenSharingCallback;
|
private readonly stopLocalScreenSharingStreamCallback: StopScreenSharingCallback;
|
||||||
@ -140,8 +140,8 @@ export class SimplePeer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaManager.removeActiveVideo(user.userId);
|
mediaManager.removeActiveVideo("" + user.userId);
|
||||||
mediaManager.addActiveVideo(user.userId, name);
|
mediaManager.addActiveVideo("" + user.userId, name);
|
||||||
|
|
||||||
const peer = new VideoPeer(user.userId, user.initiator ? user.initiator : false, this.Connection);
|
const peer = new VideoPeer(user.userId, user.initiator ? user.initiator : false, this.Connection);
|
||||||
// When a connection is established to a video stream, and if a screen sharing is taking place,
|
// When a connection is established to a video stream, and if a screen sharing is taking place,
|
||||||
@ -171,8 +171,8 @@ export class SimplePeer {
|
|||||||
|
|
||||||
// We should display the screen sharing ONLY if we are not initiator
|
// We should display the screen sharing ONLY if we are not initiator
|
||||||
if (!user.initiator) {
|
if (!user.initiator) {
|
||||||
mediaManager.removeActiveScreenSharingVideo(user.userId);
|
mediaManager.removeActiveScreenSharingVideo("" + user.userId);
|
||||||
mediaManager.addScreenSharingActiveVideo(user.userId);
|
mediaManager.addScreenSharingActiveVideo("" + user.userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const peer = new ScreenSharingPeer(user.userId, user.initiator ? user.initiator : false, this.Connection);
|
const peer = new ScreenSharingPeer(user.userId, user.initiator ? user.initiator : false, this.Connection);
|
||||||
@ -189,7 +189,7 @@ export class SimplePeer {
|
|||||||
*
|
*
|
||||||
* @param userId
|
* @param userId
|
||||||
*/
|
*/
|
||||||
private closeConnection(userId : string) {
|
private closeConnection(userId : number) {
|
||||||
try {
|
try {
|
||||||
//mediaManager.removeActiveVideo(userId);
|
//mediaManager.removeActiveVideo(userId);
|
||||||
const peer = this.PeerConnectionArray.get(userId);
|
const peer = this.PeerConnectionArray.get(userId);
|
||||||
@ -217,9 +217,9 @@ export class SimplePeer {
|
|||||||
*
|
*
|
||||||
* @param userId
|
* @param userId
|
||||||
*/
|
*/
|
||||||
private closeScreenSharingConnection(userId : string) {
|
private closeScreenSharingConnection(userId : number) {
|
||||||
try {
|
try {
|
||||||
mediaManager.removeActiveScreenSharingVideo(userId);
|
mediaManager.removeActiveScreenSharingVideo("" + userId);
|
||||||
const peer = this.PeerScreenSharingConnectionArray.get(userId);
|
const peer = this.PeerScreenSharingConnectionArray.get(userId);
|
||||||
if (peer === undefined) {
|
if (peer === undefined) {
|
||||||
console.warn("Tried to close connection for user "+userId+" but could not find user")
|
console.warn("Tried to close connection for user "+userId+" but could not find user")
|
||||||
@ -293,7 +293,7 @@ export class SimplePeer {
|
|||||||
*
|
*
|
||||||
* @param userId
|
* @param userId
|
||||||
*/
|
*/
|
||||||
private pushVideoToRemoteUser(userId : string) {
|
private pushVideoToRemoteUser(userId : number) {
|
||||||
try {
|
try {
|
||||||
const PeerConnection = this.PeerConnectionArray.get(userId);
|
const PeerConnection = this.PeerConnectionArray.get(userId);
|
||||||
if (!PeerConnection) {
|
if (!PeerConnection) {
|
||||||
@ -314,7 +314,7 @@ export class SimplePeer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private pushScreenSharingToRemoteUser(userId : string) {
|
private pushScreenSharingToRemoteUser(userId : number) {
|
||||||
const PeerConnection = this.PeerScreenSharingConnectionArray.get(userId);
|
const PeerConnection = this.PeerScreenSharingConnectionArray.get(userId);
|
||||||
if (!PeerConnection) {
|
if (!PeerConnection) {
|
||||||
throw new Error('While pushing screen sharing, cannot find user with ID ' + userId);
|
throw new Error('While pushing screen sharing, cannot find user with ID ' + userId);
|
||||||
@ -359,7 +359,7 @@ export class SimplePeer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private sendLocalScreenSharingStreamToUser(userId: string): void {
|
private sendLocalScreenSharingStreamToUser(userId: number): void {
|
||||||
// If a connection already exists with user (because it is already sharing a screen with us... let's use this connection)
|
// If a connection already exists with user (because it is already sharing a screen with us... let's use this connection)
|
||||||
if (this.PeerScreenSharingConnectionArray.has(userId)) {
|
if (this.PeerScreenSharingConnectionArray.has(userId)) {
|
||||||
this.pushScreenSharingToRemoteUser(userId);
|
this.pushScreenSharingToRemoteUser(userId);
|
||||||
@ -376,7 +376,7 @@ export class SimplePeer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private stopLocalScreenSharingStreamToUser(userId: string, stream: MediaStream): void {
|
private stopLocalScreenSharingStreamToUser(userId: number, stream: MediaStream): void {
|
||||||
const PeerConnectionScreenSharing = this.PeerScreenSharingConnectionArray.get(userId);
|
const PeerConnectionScreenSharing = this.PeerScreenSharingConnectionArray.get(userId);
|
||||||
if (!PeerConnectionScreenSharing) {
|
if (!PeerConnectionScreenSharing) {
|
||||||
throw new Error('Weird, screen sharing connection to user ' + userId + 'not found')
|
throw new Error('Weird, screen sharing connection to user ' + userId + 'not found')
|
||||||
|
@ -9,7 +9,7 @@ const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
|||||||
* A peer connection used to transmit video / audio signals between 2 peers.
|
* A peer connection used to transmit video / audio signals between 2 peers.
|
||||||
*/
|
*/
|
||||||
export class VideoPeer extends Peer {
|
export class VideoPeer extends Peer {
|
||||||
constructor(private userId: string, initiator: boolean, private connection: Connection) {
|
constructor(private userId: number, initiator: boolean, private connection: Connection) {
|
||||||
super({
|
super({
|
||||||
initiator: initiator ? initiator : false,
|
initiator: initiator ? initiator : false,
|
||||||
reconnectTimer: 10000,
|
reconnectTimer: 10000,
|
||||||
@ -63,11 +63,11 @@ export class VideoPeer extends Peer {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
this.on('error', (err: any) => {
|
this.on('error', (err: any) => {
|
||||||
console.error(`error => ${this.userId} => ${err.code}`, err);
|
console.error(`error => ${this.userId} => ${err.code}`, err);
|
||||||
mediaManager.isError(userId);
|
mediaManager.isError("" + userId);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.on('connect', () => {
|
this.on('connect', () => {
|
||||||
mediaManager.isConnected(this.userId);
|
mediaManager.isConnected("" + this.userId);
|
||||||
console.info(`connect => ${this.userId}`);
|
console.info(`connect => ${this.userId}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ export class VideoPeer extends Peer {
|
|||||||
mediaManager.disabledVideoByUserId(this.userId);
|
mediaManager.disabledVideoByUserId(this.userId);
|
||||||
mediaManager.disabledMicrophoneByUserId(this.userId);
|
mediaManager.disabledMicrophoneByUserId(this.userId);
|
||||||
} else {
|
} else {
|
||||||
mediaManager.addStreamRemoteVideo(this.userId, stream);
|
mediaManager.addStreamRemoteVideo("" + this.userId, stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ export class VideoPeer extends Peer {
|
|||||||
*/
|
*/
|
||||||
public destroy(error?: Error): void {
|
public destroy(error?: Error): void {
|
||||||
try {
|
try {
|
||||||
mediaManager.removeActiveVideo(this.userId);
|
mediaManager.removeActiveVideo("" + this.userId);
|
||||||
// FIXME: I don't understand why "Closing connection with" message is displayed TWICE before "Nb users in peerConnectionArray"
|
// FIXME: I don't understand why "Closing connection with" message is displayed TWICE before "Nb users in peerConnectionArray"
|
||||||
// I do understand the method closeConnection is called twice, but I don't understand how they manage to run in parallel.
|
// I do understand the method closeConnection is called twice, but I don't understand how they manage to run in parallel.
|
||||||
//console.log('Closing connection with '+userId);
|
//console.log('Closing connection with '+userId);
|
||||||
|
3
messages/generated/.gitignore
vendored
3
messages/generated/.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
src/
|
*
|
||||||
|
!.gitignore
|
||||||
|
31
messages/generated/src/proto/messages_pb.d.ts
vendored
31
messages/generated/src/proto/messages_pb.d.ts
vendored
@ -1,31 +0,0 @@
|
|||||||
// package:
|
|
||||||
// file: src/proto/messages.proto
|
|
||||||
|
|
||||||
import * as jspb from "google-protobuf";
|
|
||||||
|
|
||||||
export class SetPlayerDetailsMessage extends jspb.Message {
|
|
||||||
getName(): string;
|
|
||||||
setName(value: string): void;
|
|
||||||
|
|
||||||
clearCharacterlayersList(): void;
|
|
||||||
getCharacterlayersList(): Array<string>;
|
|
||||||
setCharacterlayersList(value: Array<string>): void;
|
|
||||||
addCharacterlayers(value: string, index?: number): string;
|
|
||||||
|
|
||||||
serializeBinary(): Uint8Array;
|
|
||||||
toObject(includeInstance?: boolean): SetPlayerDetailsMessage.AsObject;
|
|
||||||
static toObject(includeInstance: boolean, msg: SetPlayerDetailsMessage): SetPlayerDetailsMessage.AsObject;
|
|
||||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
|
||||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
|
||||||
static serializeBinaryToWriter(message: SetPlayerDetailsMessage, writer: jspb.BinaryWriter): void;
|
|
||||||
static deserializeBinary(bytes: Uint8Array): SetPlayerDetailsMessage;
|
|
||||||
static deserializeBinaryFromReader(message: SetPlayerDetailsMessage, reader: jspb.BinaryReader): SetPlayerDetailsMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
export namespace SetPlayerDetailsMessage {
|
|
||||||
export type AsObject = {
|
|
||||||
name: string,
|
|
||||||
characterlayersList: Array<string>,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,223 +0,0 @@
|
|||||||
// source: src/proto/messages.proto
|
|
||||||
/**
|
|
||||||
* @fileoverview
|
|
||||||
* @enhanceable
|
|
||||||
* @suppress {messageConventions} JS Compiler reports an error if a variable or
|
|
||||||
* field starts with 'MSG_' and isn't a translatable message.
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
// GENERATED CODE -- DO NOT EDIT!
|
|
||||||
|
|
||||||
var jspb = require('google-protobuf');
|
|
||||||
var goog = jspb;
|
|
||||||
var global = Function('return this')();
|
|
||||||
|
|
||||||
goog.exportSymbol('proto.SetPlayerDetailsMessage', null, global);
|
|
||||||
/**
|
|
||||||
* Generated by JsPbCodeGenerator.
|
|
||||||
* @param {Array=} opt_data Optional initial data array, typically from a
|
|
||||||
* server response, or constructed directly in Javascript. The array is used
|
|
||||||
* in place and becomes part of the constructed object. It is not cloned.
|
|
||||||
* If no data is provided, the constructed object will be empty, but still
|
|
||||||
* valid.
|
|
||||||
* @extends {jspb.Message}
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage = function(opt_data) {
|
|
||||||
jspb.Message.initialize(this, opt_data, 0, -1, proto.SetPlayerDetailsMessage.repeatedFields_, null);
|
|
||||||
};
|
|
||||||
goog.inherits(proto.SetPlayerDetailsMessage, jspb.Message);
|
|
||||||
if (goog.DEBUG && !COMPILED) {
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.displayName = 'proto.SetPlayerDetailsMessage';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of repeated fields within this message type.
|
|
||||||
* @private {!Array<number>}
|
|
||||||
* @const
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.repeatedFields_ = [2];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (jspb.Message.GENERATE_TO_OBJECT) {
|
|
||||||
/**
|
|
||||||
* Creates an object representation of this proto.
|
|
||||||
* Field names that are reserved in JavaScript and will be renamed to pb_name.
|
|
||||||
* Optional fields that are not set will be set to undefined.
|
|
||||||
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
|
|
||||||
* For the list of reserved names please see:
|
|
||||||
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
|
|
||||||
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
|
|
||||||
* JSPB instance for transitional soy proto support:
|
|
||||||
* http://goto/soy-param-migration
|
|
||||||
* @return {!Object}
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.prototype.toObject = function(opt_includeInstance) {
|
|
||||||
return proto.SetPlayerDetailsMessage.toObject(opt_includeInstance, this);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Static version of the {@see toObject} method.
|
|
||||||
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
|
|
||||||
* the JSPB instance for transitional soy proto support:
|
|
||||||
* http://goto/soy-param-migration
|
|
||||||
* @param {!proto.SetPlayerDetailsMessage} msg The msg instance to transform.
|
|
||||||
* @return {!Object}
|
|
||||||
* @suppress {unusedLocalVariables} f is only used for nested messages
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.toObject = function(includeInstance, msg) {
|
|
||||||
var f, obj = {
|
|
||||||
name: jspb.Message.getFieldWithDefault(msg, 1, ""),
|
|
||||||
characterlayersList: (f = jspb.Message.getRepeatedField(msg, 2)) == null ? undefined : f
|
|
||||||
};
|
|
||||||
|
|
||||||
if (includeInstance) {
|
|
||||||
obj.$jspbMessageInstance = msg;
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deserializes binary data (in protobuf wire format).
|
|
||||||
* @param {jspb.ByteSource} bytes The bytes to deserialize.
|
|
||||||
* @return {!proto.SetPlayerDetailsMessage}
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.deserializeBinary = function(bytes) {
|
|
||||||
var reader = new jspb.BinaryReader(bytes);
|
|
||||||
var msg = new proto.SetPlayerDetailsMessage;
|
|
||||||
return proto.SetPlayerDetailsMessage.deserializeBinaryFromReader(msg, reader);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deserializes binary data (in protobuf wire format) from the
|
|
||||||
* given reader into the given message object.
|
|
||||||
* @param {!proto.SetPlayerDetailsMessage} msg The message object to deserialize into.
|
|
||||||
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
|
|
||||||
* @return {!proto.SetPlayerDetailsMessage}
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.deserializeBinaryFromReader = function(msg, reader) {
|
|
||||||
while (reader.nextField()) {
|
|
||||||
if (reader.isEndGroup()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
var field = reader.getFieldNumber();
|
|
||||||
switch (field) {
|
|
||||||
case 1:
|
|
||||||
var value = /** @type {string} */ (reader.readString());
|
|
||||||
msg.setName(value);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
var value = /** @type {string} */ (reader.readString());
|
|
||||||
msg.addCharacterlayers(value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
reader.skipField();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return msg;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serializes the message to binary data (in protobuf wire format).
|
|
||||||
* @return {!Uint8Array}
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.prototype.serializeBinary = function() {
|
|
||||||
var writer = new jspb.BinaryWriter();
|
|
||||||
proto.SetPlayerDetailsMessage.serializeBinaryToWriter(this, writer);
|
|
||||||
return writer.getResultBuffer();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serializes the given message to binary data (in protobuf wire
|
|
||||||
* format), writing to the given BinaryWriter.
|
|
||||||
* @param {!proto.SetPlayerDetailsMessage} message
|
|
||||||
* @param {!jspb.BinaryWriter} writer
|
|
||||||
* @suppress {unusedLocalVariables} f is only used for nested messages
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.serializeBinaryToWriter = function(message, writer) {
|
|
||||||
var f = undefined;
|
|
||||||
f = message.getName();
|
|
||||||
if (f.length > 0) {
|
|
||||||
writer.writeString(
|
|
||||||
1,
|
|
||||||
f
|
|
||||||
);
|
|
||||||
}
|
|
||||||
f = message.getCharacterlayersList();
|
|
||||||
if (f.length > 0) {
|
|
||||||
writer.writeRepeatedString(
|
|
||||||
2,
|
|
||||||
f
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* optional string name = 1;
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.prototype.getName = function() {
|
|
||||||
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} value
|
|
||||||
* @return {!proto.SetPlayerDetailsMessage} returns this
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.prototype.setName = function(value) {
|
|
||||||
return jspb.Message.setProto3StringField(this, 1, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* repeated string characterLayers = 2;
|
|
||||||
* @return {!Array<string>}
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.prototype.getCharacterlayersList = function() {
|
|
||||||
return /** @type {!Array<string>} */ (jspb.Message.getRepeatedField(this, 2));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {!Array<string>} value
|
|
||||||
* @return {!proto.SetPlayerDetailsMessage} returns this
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.prototype.setCharacterlayersList = function(value) {
|
|
||||||
return jspb.Message.setField(this, 2, value || []);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} value
|
|
||||||
* @param {number=} opt_index
|
|
||||||
* @return {!proto.SetPlayerDetailsMessage} returns this
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.prototype.addCharacterlayers = function(value, opt_index) {
|
|
||||||
return jspb.Message.addToRepeatedField(this, 2, value, opt_index);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the list making it empty but non-null.
|
|
||||||
* @return {!proto.SetPlayerDetailsMessage} returns this
|
|
||||||
*/
|
|
||||||
proto.SetPlayerDetailsMessage.prototype.clearCharacterlayersList = function() {
|
|
||||||
return this.setCharacterlayersList([]);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
goog.object.extend(exports, proto);
|
|
@ -1,6 +1,41 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
|
/*********** CLIENT TO SERVER MESSAGES *************/
|
||||||
|
|
||||||
message SetPlayerDetailsMessage {
|
message SetPlayerDetailsMessage {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
repeated string characterLayers = 2;
|
repeated string characterLayers = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message PositionMessage {
|
||||||
|
int32 x = 1;
|
||||||
|
int32 y = 2;
|
||||||
|
enum Direction {
|
||||||
|
UP = 0;
|
||||||
|
RIGHT = 1;
|
||||||
|
DOWN = 2;
|
||||||
|
LEFT = 3;
|
||||||
|
}
|
||||||
|
Direction direction = 3;
|
||||||
|
bool moving = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ViewportMessage {
|
||||||
|
int32 left = 1;
|
||||||
|
int32 top = 2;
|
||||||
|
int32 right = 3;
|
||||||
|
int32 bottom = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UserMovesMessage {
|
||||||
|
PositionMessage position = 1;
|
||||||
|
ViewportMessage viewport = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*********** SERVER TO CLIENT MESSAGES *************/
|
||||||
|
|
||||||
|
message UserMovedMessage {
|
||||||
|
int32 userId = 1;
|
||||||
|
PositionMessage position = 2;
|
||||||
|
}
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "generated/src/proto/messages_pb.js",
|
"main": "generated/src/proto/messages_pb.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"proto": "protoc --plugin=\"protoc-gen-ts=./node_modules/.bin/protoc-gen-ts\" --js_out=\"import_style=commonjs,binary:src/messages/generated\" --ts_out=\"src/messages/generated\" src/messages/messages.proto",
|
"proto": "protoc --plugin=\"protoc-gen-ts=./node_modules/.bin/protoc-gen-ts\" --js_out=\"import_style=commonjs,binary:generated\" --ts_out=\"generated\" messages.proto",
|
||||||
"proto:watch": "inotifywait -q -m -e close_write src/messages/messages.proto | while read -r filename event; do yarn run proto; done"
|
"proto:watch": "inotifywait -q -m -e close_write messages.proto | while read -r filename event; do yarn run proto; done"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
Loading…
Reference in New Issue
Block a user