Merge branch 'develop' of github.com:thecodingmachine/workadventure into uws
# Conflicts: # back/src/Controller/AdminController.ts # back/src/Controller/AuthenticateController.ts # back/src/Controller/IoSocketController.ts # back/src/Controller/MapController.ts # benchmark/index.ts # front/src/Connexion/RoomConnection.ts
This commit is contained in:
commit
9f3577286d
@ -3,7 +3,6 @@ import {IoSocketController} from "./Controller/IoSocketController"; //TODO fix i
|
|||||||
import {AuthenticateController} from "./Controller/AuthenticateController"; //TODO fix import by "_Controller/..."
|
import {AuthenticateController} from "./Controller/AuthenticateController"; //TODO fix import by "_Controller/..."
|
||||||
import {MapController} from "./Controller/MapController";
|
import {MapController} from "./Controller/MapController";
|
||||||
import {PrometheusController} from "./Controller/PrometheusController";
|
import {PrometheusController} from "./Controller/PrometheusController";
|
||||||
import {AdminController} from "./Controller/AdminController";
|
|
||||||
import {DebugController} from "./Controller/DebugController";
|
import {DebugController} from "./Controller/DebugController";
|
||||||
import {App as uwsApp} from "./Server/sifrr.server";
|
import {App as uwsApp} from "./Server/sifrr.server";
|
||||||
|
|
||||||
@ -13,7 +12,6 @@ class App {
|
|||||||
public authenticateController: AuthenticateController;
|
public authenticateController: AuthenticateController;
|
||||||
public mapController: MapController;
|
public mapController: MapController;
|
||||||
public prometheusController: PrometheusController;
|
public prometheusController: PrometheusController;
|
||||||
private adminController: AdminController;
|
|
||||||
private debugController: DebugController;
|
private debugController: DebugController;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -39,7 +37,6 @@ class App {
|
|||||||
this.authenticateController = new AuthenticateController(this.app);
|
this.authenticateController = new AuthenticateController(this.app);
|
||||||
this.mapController = new MapController(this.app);
|
this.mapController = new MapController(this.app);
|
||||||
this.prometheusController = new PrometheusController(this.app, this.ioSocketController);
|
this.prometheusController = new PrometheusController(this.app, this.ioSocketController);
|
||||||
this.adminController = new AdminController(this.app);
|
|
||||||
this.debugController = new DebugController(this.app, this.ioSocketController);
|
this.debugController = new DebugController(this.app, this.ioSocketController);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
import {OK} from "http-status-codes";
|
|
||||||
import {ADMIN_API_TOKEN, ADMIN_API_URL} from "../Enum/EnvironmentVariable";
|
|
||||||
import Axios from "axios";
|
|
||||||
import {HttpRequest, HttpResponse} from "uWebSockets.js";
|
|
||||||
import {parse} from "query-string";
|
|
||||||
import {App} from "../Server/sifrr.server";
|
|
||||||
|
|
||||||
export class AdminController {
|
|
||||||
constructor(private App : App) {
|
|
||||||
this.getLoginUrlByToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
getLoginUrlByToken(){
|
|
||||||
this.App.get("/register/:token", (res: HttpResponse, req: HttpRequest) => {
|
|
||||||
(async () => {
|
|
||||||
if (!ADMIN_API_URL) {
|
|
||||||
return res.writeStatus("500 Internal Server Error").end('No admin backoffice set!');
|
|
||||||
}
|
|
||||||
|
|
||||||
const query = parse(req.getQuery());
|
|
||||||
|
|
||||||
const token:string = query.token as string;
|
|
||||||
|
|
||||||
let response = null
|
|
||||||
try {
|
|
||||||
response = await Axios.get(ADMIN_API_URL+'/api/login-url/'+token, { headers: {"Authorization" : `${ADMIN_API_TOKEN}`} })
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e.message)
|
|
||||||
return res.status(e.status || 500).send('An error happened');
|
|
||||||
}
|
|
||||||
|
|
||||||
const organizationSlug = response.data.organizationSlug;
|
|
||||||
const worldSlug = response.data.worldSlug;
|
|
||||||
const roomSlug = response.data.roomSlug;
|
|
||||||
res.writeStatus("200 OK").end(JSON.stringify({organizationSlug, worldSlug, roomSlug}));
|
|
||||||
})();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,21 @@
|
|||||||
import Jwt from "jsonwebtoken";
|
import Jwt from "jsonwebtoken";
|
||||||
import {SECRET_KEY, URL_ROOM_STARTED} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
|
import {SECRET_KEY, URL_ROOM_STARTED} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
|
||||||
|
import {OK} from "http-status-codes";
|
||||||
|
import {ADMIN_API_TOKEN, ADMIN_API_URL, SECRET_KEY, URL_ROOM_STARTED} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
|
||||||
import { uuid } from 'uuidv4';
|
import { uuid } from 'uuidv4';
|
||||||
import {HttpRequest, HttpResponse, TemplatedApp} from "uWebSockets.js";
|
import {HttpRequest, HttpResponse, TemplatedApp} from "uWebSockets.js";
|
||||||
import {BaseController} from "./BaseController";
|
import {BaseController} from "./BaseController";
|
||||||
|
import Axios from "axios";
|
||||||
|
|
||||||
export interface TokenInterface {
|
export interface TokenInterface {
|
||||||
name: string,
|
userUuid: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AdminApiData {
|
||||||
|
organizationSlug: string
|
||||||
|
worldSlug: string
|
||||||
|
roomSlug: string
|
||||||
|
mapUrlStart: string
|
||||||
userUuid: string
|
userUuid: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,21 +26,6 @@ export class AuthenticateController extends BaseController {
|
|||||||
this.login();
|
this.login();
|
||||||
}
|
}
|
||||||
|
|
||||||
onAbortedOrFinishedResponse(res: HttpResponse/*, readStream: any*/) {
|
|
||||||
|
|
||||||
console.log("ERROR! onAbortedOrFinishedResponse called!");
|
|
||||||
/*if (res.id == -1) {
|
|
||||||
console.log("ERROR! onAbortedOrFinishedResponse called twice for the same res!");
|
|
||||||
} else {
|
|
||||||
console.log('Stream was closed, openStreams: ' + --openStreams);
|
|
||||||
console.timeEnd(res.id);
|
|
||||||
readStream.destroy();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/* Mark this response already accounted for */
|
|
||||||
//res.id = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//permit to login on application. Return token to connect on Websocket IO.
|
//permit to login on application. Return token to connect on Websocket IO.
|
||||||
login(){
|
login(){
|
||||||
this.App.options("/login", (res: HttpResponse, req: HttpRequest) => {
|
this.App.options("/login", (res: HttpResponse, req: HttpRequest) => {
|
||||||
@ -47,14 +42,55 @@ export class AuthenticateController extends BaseController {
|
|||||||
console.warn('Login request was aborted');
|
console.warn('Login request was aborted');
|
||||||
})
|
})
|
||||||
const param = await res.json();
|
const param = await res.json();
|
||||||
const userUuid = uuid();
|
|
||||||
const token = Jwt.sign({name: param.name, userUuid: userUuid} as TokenInterface, SECRET_KEY, {expiresIn: '24h'});
|
//todo: what to do if the organizationMemberToken is already used?
|
||||||
res.writeStatus("200 OK").end(JSON.stringify({
|
const organizationMemberToken:string|null = param.organizationMemberToken;
|
||||||
token: token,
|
|
||||||
mapUrlStart: URL_ROOM_STARTED,
|
try {
|
||||||
userId: userUuid,
|
let userUuid;
|
||||||
}));
|
let mapUrlStart;
|
||||||
|
let newUrl = null;
|
||||||
|
|
||||||
|
if (organizationMemberToken) {
|
||||||
|
if (!ADMIN_API_URL) {
|
||||||
|
return res.status(401).send('No admin backoffice set!');
|
||||||
|
}
|
||||||
|
//todo: this call can fail if the corresponding world is not activated or if the token is invalid. Handle that case.
|
||||||
|
const data = await Axios.get(ADMIN_API_URL+'/api/login-url/'+organizationMemberToken,
|
||||||
|
{ headers: {"Authorization" : `${ADMIN_API_TOKEN}`} }
|
||||||
|
).then((res): AdminApiData => res.data);
|
||||||
|
|
||||||
|
userUuid = data.userUuid;
|
||||||
|
mapUrlStart = data.mapUrlStart;
|
||||||
|
newUrl = this.getNewUrlOnAdminAuth(data)
|
||||||
|
} else {
|
||||||
|
userUuid = uuid();
|
||||||
|
mapUrlStart = req.getHeader('host').replace('api.', 'maps.') + URL_ROOM_STARTED;
|
||||||
|
newUrl = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const authToken = Jwt.sign({userUuid: userUuid}, SECRET_KEY, {expiresIn: '24h'});
|
||||||
|
res.writeStatus("200 OK").end(JSON.stringify({
|
||||||
|
authToken,
|
||||||
|
userUuid,
|
||||||
|
mapUrlStart,
|
||||||
|
newUrl,
|
||||||
|
}));
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e.message)
|
||||||
|
res.writeStatus(e.status || "500 Internal Server Error").end('An error happened');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
})();
|
})();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getNewUrlOnAdminAuth(data:AdminApiData): string {
|
||||||
|
const organizationSlug = data.organizationSlug;
|
||||||
|
const worldSlug = data.worldSlug;
|
||||||
|
const roomSlug = data.roomSlug;
|
||||||
|
return '/@/'+organizationSlug+'/'+worldSlug+'/'+roomSlug;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,9 +116,6 @@ export class IoSocketController {
|
|||||||
if (typeof((token as TokenInterface).userUuid) !== 'string') {
|
if (typeof((token as TokenInterface).userUuid) !== 'string') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (typeof((token as TokenInterface).name) !== 'string') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,45 +139,46 @@ export class IoSocketController {
|
|||||||
//console.log(socket.handshake.query.token);
|
//console.log(socket.handshake.query.token);
|
||||||
|
|
||||||
/*if (!socket.handshake.query || !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.');
|
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'));
|
return next(new Error('Authentication error'));
|
||||||
}
|
}
|
||||||
|
if(socket.handshake.query.token === 'test'){
|
||||||
if (!this.isValidToken(tokenDecoded)) {
|
if (ALLOW_ARTILLERY) {
|
||||||
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 = 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) => {
|
||||||
|
const tokenInterface = tokenDecoded as TokenInterface;
|
||||||
|
if (err) {
|
||||||
|
console.error('An authentication error happened, invalid JsonWebToken.', err);
|
||||||
|
return next(new Error('Authentication error'));
|
||||||
|
}
|
||||||
|
|
||||||
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
if (!this.isValidToken(tokenInterface)) {
|
||||||
(socket as ExSocketInterface).userId = this.nextUserId;
|
return next(new Error('Authentication error, invalid token structure'));
|
||||||
(socket as ExSocketInterface).userUuid = tokenDecoded.userUuid;
|
}
|
||||||
this.nextUserId++;
|
|
||||||
next();
|
(socket as ExSocketInterface).token = socket.handshake.query.token;
|
||||||
});*/
|
(socket as ExSocketInterface).userId = this.nextUserId;
|
||||||
|
(socket as ExSocketInterface).userUuid = tokenInterface.userUuid;
|
||||||
|
this.nextUserId++;
|
||||||
|
next();
|
||||||
|
});*/
|
||||||
const socket = ws as ExSocketInterface;
|
const socket = ws as ExSocketInterface;
|
||||||
socket.userId = this.nextUserId;
|
socket.userId = this.nextUserId;
|
||||||
this.nextUserId++;
|
this.nextUserId++;
|
||||||
|
@ -3,6 +3,7 @@ import {URL_ROOM_STARTED} from "../Enum/EnvironmentVariable";
|
|||||||
import {HttpRequest, HttpResponse, TemplatedApp} from "uWebSockets.js";
|
import {HttpRequest, HttpResponse, TemplatedApp} from "uWebSockets.js";
|
||||||
import {BaseController} from "./BaseController";
|
import {BaseController} from "./BaseController";
|
||||||
|
|
||||||
|
//todo: delete this
|
||||||
export class MapController extends BaseController{
|
export class MapController extends BaseController{
|
||||||
|
|
||||||
constructor(private App : TemplatedApp) {
|
constructor(private App : TemplatedApp) {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import {PointInterface} from "./PointInterface";
|
import {PointInterface} from "./PointInterface";
|
||||||
import {Identificable} from "./Identificable";
|
import {Identificable} from "./Identificable";
|
||||||
import {TokenInterface} from "../../Controller/AuthenticateController";
|
|
||||||
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
|
import {ViewportInterface} from "_Model/Websocket/ViewportMessage";
|
||||||
import {BatchMessage, SubMessage} from "../../Messages/generated/messages_pb";
|
import {BatchMessage, SubMessage} from "../../Messages/generated/messages_pb";
|
||||||
import {WebSocket} from "uWebSockets.js"
|
import {WebSocket} from "uWebSockets.js"
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import {Connection} from "../front/src/Connection";
|
import {RoomConnection} from "../front/src/Connexion/Connection";
|
||||||
import * as WebSocket from "ws"
|
import * as WebSocket from "ws"
|
||||||
|
|
||||||
function sleep(ms) {
|
function sleep(ms) {
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection.setWebsocketFactory((url: string) => {
|
RoomConnection.setWebsocketFactory((url: string) => {
|
||||||
return new WebSocket(url);
|
return new WebSocket(url);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function startOneUser(): Promise<void> {
|
async function startOneUser(): Promise<void> {
|
||||||
const connection = await Connection.createConnection('foo', ['male3']);
|
const connection = await RoomConnection.createConnection('foo', ['male3']);
|
||||||
|
|
||||||
await connection.joinARoom('global__maps.workadventure.localhost/Floor0/floor0', 783, 170, 'down', false, {
|
await connection.joinARoom('global__maps.workadventure.localhost/Floor0/floor0', 783, 170, 'down', false, {
|
||||||
top: 0,
|
top: 0,
|
||||||
|
65
front/src/Connexion/ConnectionManager.ts
Normal file
65
front/src/Connexion/ConnectionManager.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import Axios from "axios";
|
||||||
|
import {API_URL} from "../Enum/EnvironmentVariable";
|
||||||
|
import {RoomConnection} from "./RoomConnection";
|
||||||
|
|
||||||
|
interface LoginApiData {
|
||||||
|
authToken: string
|
||||||
|
userUuid: string
|
||||||
|
mapUrlStart: string
|
||||||
|
newUrl: string
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConnectionManager {
|
||||||
|
private initPromise: Promise<LoginApiData> = Promise.reject();
|
||||||
|
private mapUrlStart: string|null = null;
|
||||||
|
|
||||||
|
private authToken:string|null = null;
|
||||||
|
private userUuid: string|null = null;
|
||||||
|
|
||||||
|
public async init(): Promise<void> {
|
||||||
|
const match = /\/register\/(.+)/.exec(window.location.toString());
|
||||||
|
const organizationMemberToken = match ? match[1] : null;
|
||||||
|
this.initPromise = Axios.post(`${API_URL}/login`, {organizationMemberToken}).then(res => res.data);
|
||||||
|
const data = await this.initPromise
|
||||||
|
this.authToken = data.authToken;
|
||||||
|
this.userUuid = data.userUuid;
|
||||||
|
this.mapUrlStart = data.mapUrlStart;
|
||||||
|
const newUrl = data.newUrl;
|
||||||
|
|
||||||
|
if (newUrl) {
|
||||||
|
history.pushState({}, '', newUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public connectToRoomSocket(): Promise<RoomConnection> {
|
||||||
|
return new Promise<RoomConnection>((resolve, reject) => {
|
||||||
|
const connection = new RoomConnection(this.authToken as string);
|
||||||
|
connection.onConnectError((error: object) => {
|
||||||
|
console.log('An error occurred while connecting to socket server. Retrying');
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
connection.onConnect(() => {
|
||||||
|
resolve(connection);
|
||||||
|
})
|
||||||
|
}).catch((err) => {
|
||||||
|
// Let's retry in 4-6 seconds
|
||||||
|
return new Promise<RoomConnection>((resolve, reject) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
//todo: allow a way to break recurrsion?
|
||||||
|
this.connectToRoomSocket().then((connection) => resolve(connection));
|
||||||
|
}, 4000 + Math.floor(Math.random() * 2000) );
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMapUrlStart(): Promise<string> {
|
||||||
|
return this.initPromise.then(() => {
|
||||||
|
if (!this.mapUrlStart) {
|
||||||
|
throw new Error('No map url set!');
|
||||||
|
}
|
||||||
|
return this.mapUrlStart;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const connectionManager = new ConnectionManager();
|
117
front/src/Connexion/ConnexionModels.ts
Normal file
117
front/src/Connexion/ConnexionModels.ts
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import {PlayerAnimationNames} from "../Phaser/Player/Animation";
|
||||||
|
import {UserSimplePeerInterface} from "../WebRtc/SimplePeer";
|
||||||
|
import {SignalData} from "simple-peer";
|
||||||
|
|
||||||
|
export enum EventMessage{
|
||||||
|
WEBRTC_SIGNAL = "webrtc-signal",
|
||||||
|
WEBRTC_SCREEN_SHARING_SIGNAL = "webrtc-screen-sharing-signal",
|
||||||
|
WEBRTC_START = "webrtc-start",
|
||||||
|
JOIN_ROOM = "join-room", // bi-directional
|
||||||
|
USER_POSITION = "user-position", // From client to server
|
||||||
|
USER_MOVED = "user-moved", // From server to client
|
||||||
|
USER_LEFT = "user-left", // From server to client
|
||||||
|
MESSAGE_ERROR = "message-error",
|
||||||
|
WEBRTC_DISCONNECT = "webrtc-disconect",
|
||||||
|
GROUP_CREATE_UPDATE = "group-create-update",
|
||||||
|
GROUP_DELETE = "group-delete",
|
||||||
|
SET_PLAYER_DETAILS = "set-player-details", // Send the name and character to the server (on connect), receive back the id.
|
||||||
|
ITEM_EVENT = 'item-event',
|
||||||
|
|
||||||
|
CONNECT_ERROR = "connect_error",
|
||||||
|
SET_SILENT = "set_silent", // Set or unset the silent mode for this user.
|
||||||
|
SET_VIEWPORT = "set-viewport",
|
||||||
|
BATCH = "batch",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PointInterface {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
direction : string;
|
||||||
|
moving: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Point implements PointInterface{
|
||||||
|
constructor(public x : number, public y : number, public direction : string = PlayerAnimationNames.WalkDown, public moving : boolean = false) {
|
||||||
|
if(x === null || y === null){
|
||||||
|
throw Error("position x and y cannot be null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MessageUserPositionInterface {
|
||||||
|
userId: number;
|
||||||
|
name: string;
|
||||||
|
characterLayers: string[];
|
||||||
|
position: PointInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MessageUserMovedInterface {
|
||||||
|
userId: number;
|
||||||
|
position: PointInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MessageUserJoined {
|
||||||
|
userId: number;
|
||||||
|
name: string;
|
||||||
|
characterLayers: string[];
|
||||||
|
position: PointInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PositionInterface {
|
||||||
|
x: number,
|
||||||
|
y: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GroupCreatedUpdatedMessageInterface {
|
||||||
|
position: PositionInterface,
|
||||||
|
groupId: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WebRtcStartMessageInterface {
|
||||||
|
roomId: string,
|
||||||
|
clients: UserSimplePeerInterface[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WebRtcDisconnectMessageInterface {
|
||||||
|
userId: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WebRtcSignalSentMessageInterface {
|
||||||
|
receiverId: number,
|
||||||
|
signal: SignalData
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WebRtcSignalReceivedMessageInterface {
|
||||||
|
userId: number,
|
||||||
|
signal: SignalData
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StartMapInterface {
|
||||||
|
mapUrlStart: string,
|
||||||
|
startInstance: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ViewportInterface {
|
||||||
|
left: number,
|
||||||
|
top: number,
|
||||||
|
right: number,
|
||||||
|
bottom: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BatchedMessageInterface {
|
||||||
|
event: string,
|
||||||
|
payload: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ItemEventMessageInterface {
|
||||||
|
itemId: number,
|
||||||
|
event: string,
|
||||||
|
state: unknown,
|
||||||
|
parameters: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RoomJoinedMessageInterface {
|
||||||
|
users: MessageUserPositionInterface[],
|
||||||
|
groups: GroupCreatedUpdatedMessageInterface[],
|
||||||
|
items: { [itemId: number] : unknown }
|
||||||
|
}
|
@ -1,6 +1,4 @@
|
|||||||
import Axios from "axios";
|
import {API_URL} from "../Enum/EnvironmentVariable";
|
||||||
import {API_URL} from "./Enum/EnvironmentVariable";
|
|
||||||
import {MessageUI} from "./Logger/MessageUI";
|
|
||||||
import {
|
import {
|
||||||
BatchMessage,
|
BatchMessage,
|
||||||
ClientToServerMessage,
|
ClientToServerMessage,
|
||||||
@ -23,144 +21,39 @@ import {
|
|||||||
WebRtcSignalToClientMessage,
|
WebRtcSignalToClientMessage,
|
||||||
WebRtcSignalToServerMessage,
|
WebRtcSignalToServerMessage,
|
||||||
WebRtcStartMessage
|
WebRtcStartMessage
|
||||||
} from "./Messages/generated/messages_pb"
|
} from "../Messages/generated/messages_pb"
|
||||||
|
|
||||||
import {PlayerAnimationNames} from "./Phaser/Player/Animation";
|
import {UserSimplePeerInterface} from "../WebRtc/SimplePeer";
|
||||||
import {UserSimplePeerInterface} from "./WebRtc/SimplePeer";
|
|
||||||
import {SignalData} from "simple-peer";
|
|
||||||
import Direction = PositionMessage.Direction;
|
import Direction = PositionMessage.Direction;
|
||||||
import {ProtobufClientUtils} from "./Network/ProtobufClientUtils";
|
import {ProtobufClientUtils} from "../Network/ProtobufClientUtils";
|
||||||
|
import {
|
||||||
|
EventMessage,
|
||||||
|
GroupCreatedUpdatedMessageInterface, ItemEventMessageInterface,
|
||||||
|
MessageUserJoined,
|
||||||
|
RoomJoinedMessageInterface,
|
||||||
|
ViewportInterface, WebRtcDisconnectMessageInterface,
|
||||||
|
WebRtcSignalReceivedMessageInterface,
|
||||||
|
WebRtcSignalSentMessageInterface,
|
||||||
|
WebRtcStartMessageInterface
|
||||||
|
} from "./ConnexionModels";
|
||||||
|
|
||||||
enum EventMessage{
|
|
||||||
WEBRTC_SIGNAL = "webrtc-signal",
|
|
||||||
WEBRTC_SCREEN_SHARING_SIGNAL = "webrtc-screen-sharing-signal",
|
|
||||||
WEBRTC_START = "webrtc-start",
|
|
||||||
JOIN_ROOM = "join-room", // bi-directional
|
|
||||||
USER_POSITION = "user-position", // From client to server
|
|
||||||
USER_MOVED = "user-moved", // From server to client
|
|
||||||
USER_LEFT = "user-left", // From server to client
|
|
||||||
MESSAGE_ERROR = "message-error",
|
|
||||||
WEBRTC_DISCONNECT = "webrtc-disconect",
|
|
||||||
GROUP_CREATE_UPDATE = "group-create-update",
|
|
||||||
GROUP_DELETE = "group-delete",
|
|
||||||
SET_PLAYER_DETAILS = "set-player-details", // Send the name and character to the server (on connect), receive back the id.
|
|
||||||
ITEM_EVENT = 'item-event',
|
|
||||||
|
|
||||||
CONNECT_ERROR = "connect_error",
|
export class RoomConnection implements RoomConnection {
|
||||||
SET_SILENT = "set_silent", // Set or unset the silent mode for this user.
|
|
||||||
SET_VIEWPORT = "set-viewport",
|
|
||||||
BATCH = "batch",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PointInterface {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
direction : string;
|
|
||||||
moving: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Point implements PointInterface{
|
|
||||||
constructor(public x : number, public y : number, public direction : string = PlayerAnimationNames.WalkDown, public moving : boolean = false) {
|
|
||||||
if(x === null || y === null){
|
|
||||||
throw Error("position x and y cannot be null");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MessageUserPositionInterface {
|
|
||||||
userId: number;
|
|
||||||
name: string;
|
|
||||||
characterLayers: string[];
|
|
||||||
position: PointInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MessageUserMovedInterface {
|
|
||||||
userId: number;
|
|
||||||
position: PointInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MessageUserJoined {
|
|
||||||
userId: number;
|
|
||||||
name: string;
|
|
||||||
characterLayers: string[];
|
|
||||||
position: PointInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PositionInterface {
|
|
||||||
x: number,
|
|
||||||
y: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GroupCreatedUpdatedMessageInterface {
|
|
||||||
position: PositionInterface,
|
|
||||||
groupId: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebRtcStartMessageInterface {
|
|
||||||
roomId: string,
|
|
||||||
clients: UserSimplePeerInterface[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebRtcDisconnectMessageInterface {
|
|
||||||
userId: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebRtcSignalSentMessageInterface {
|
|
||||||
receiverId: number,
|
|
||||||
signal: SignalData
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WebRtcSignalReceivedMessageInterface {
|
|
||||||
userId: number,
|
|
||||||
signal: SignalData
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface StartMapInterface {
|
|
||||||
mapUrlStart: string,
|
|
||||||
startInstance: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ViewportInterface {
|
|
||||||
left: number,
|
|
||||||
top: number,
|
|
||||||
right: number,
|
|
||||||
bottom: number,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BatchedMessageInterface {
|
|
||||||
event: string,
|
|
||||||
payload: unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ItemEventMessageInterface {
|
|
||||||
itemId: number,
|
|
||||||
event: string,
|
|
||||||
state: unknown,
|
|
||||||
parameters: unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RoomJoinedMessageInterface {
|
|
||||||
users: MessageUserPositionInterface[],
|
|
||||||
groups: GroupCreatedUpdatedMessageInterface[],
|
|
||||||
items: { [itemId: number] : unknown }
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Connection implements Connection {
|
|
||||||
private readonly socket: WebSocket;
|
private readonly socket: WebSocket;
|
||||||
private userId: number|null = null;
|
private userId: number|null = null;
|
||||||
private listeners: Map<string, Function[]> = new Map<string, Function[]>();
|
private listeners: Map<string, Function[]> = new Map<string, Function[]>();
|
||||||
private static websocketFactory: null|((url: string)=>any) = null; // eslint-disable-line @typescript-eslint/no-explicit-any
|
private static websocketFactory: null|((url: string)=>any) = null; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
|
||||||
public static setWebsocketFactory(websocketFactory: (url: string)=>any): void { // eslint-disable-line @typescript-eslint/no-explicit-any
|
public static setWebsocketFactory(websocketFactory: (url: string)=>any): void { // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
Connection.websocketFactory = websocketFactory;
|
RoomConnection.websocketFactory = websocketFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private constructor(token: string) {
|
public constructor(token: string) {
|
||||||
let url = API_URL.replace('http://', 'ws://').replace('https://', 'wss://');
|
let url = API_URL.replace('http://', 'ws://').replace('https://', 'wss://');
|
||||||
url += '?token='+token;
|
url += '?token='+token;
|
||||||
|
|
||||||
if (Connection.websocketFactory) {
|
if (RoomConnection.websocketFactory) {
|
||||||
this.socket = Connection.websocketFactory(url);
|
this.socket = RoomConnection.websocketFactory(url);
|
||||||
} else {
|
} else {
|
||||||
this.socket = new WebSocket(url);
|
this.socket = new WebSocket(url);
|
||||||
}
|
}
|
||||||
@ -248,42 +141,15 @@ export class Connection implements Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static createConnection(name: string, characterLayersSelected: string[]): Promise<Connection> {
|
public emitPlayerDetailsMessage(userName: string, characterLayersSelected: string[]) {
|
||||||
return Axios.post(`${API_URL}/login`, {name: name})
|
const message = new SetPlayerDetailsMessage();
|
||||||
.then((res) => {
|
message.setName(name);
|
||||||
|
message.setCharacterlayersList(characterLayersSelected);
|
||||||
|
|
||||||
return new Promise<Connection>((resolve, reject) => {
|
const clientToServerMessage = new ClientToServerMessage();
|
||||||
const connection = new Connection(res.data.token);
|
clientToServerMessage.setSetplayerdetailsmessage(message);
|
||||||
|
|
||||||
connection.onConnectError((error: object) => {
|
this.socket.send(clientToServerMessage.serializeBinary().buffer);
|
||||||
console.log('An error occurred while connecting to socket server. Retrying');
|
|
||||||
reject(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
connection.onConnect(() => {
|
|
||||||
const message = new SetPlayerDetailsMessage();
|
|
||||||
message.setName(name);
|
|
||||||
message.setCharacterlayersList(characterLayersSelected);
|
|
||||||
|
|
||||||
const clientToServerMessage = new ClientToServerMessage();
|
|
||||||
clientToServerMessage.setSetplayerdetailsmessage(message);
|
|
||||||
|
|
||||||
connection.socket.send(clientToServerMessage.serializeBinary().buffer);
|
|
||||||
|
|
||||||
resolve(connection);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
// Let's retry in 4-6 seconds
|
|
||||||
console.error('Connection failed. Retrying', err);
|
|
||||||
return new Promise<Connection>((resolve, reject) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
Connection.createConnection(name, characterLayersSelected).then((connection) => resolve(connection))
|
|
||||||
.catch((error) => reject(error));
|
|
||||||
}, 4000 + Math.floor(Math.random() * 2000) );
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeConnection(): void {
|
public closeConnection(): void {
|
@ -1,6 +1,6 @@
|
|||||||
import {PositionMessage} from "../Messages/generated/messages_pb";
|
import {PositionMessage} from "../Messages/generated/messages_pb";
|
||||||
import {PointInterface} from "../Connection";
|
|
||||||
import Direction = PositionMessage.Direction;
|
import Direction = PositionMessage.Direction;
|
||||||
|
import {PointInterface} from "../Connexion/ConnexionModels";
|
||||||
|
|
||||||
export class ProtobufClientUtils {
|
export class ProtobufClientUtils {
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {GameScene} from "../Game/GameScene";
|
import {GameScene} from "../Game/GameScene";
|
||||||
import {PointInterface} from "../../Connection";
|
import {PointInterface} from "../../Connexion/ConnexionModels";
|
||||||
import {Character} from "../Entity/Character";
|
import {Character} from "../Entity/Character";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {PointInterface} from "../../Connection";
|
import {PointInterface} from "../../Connexion/ConnexionModels";
|
||||||
|
|
||||||
export interface AddPlayerInterface {
|
export interface AddPlayerInterface {
|
||||||
userId: number;
|
userId: number;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import {GameScene} from "./GameScene";
|
import {GameScene} from "./GameScene";
|
||||||
import {
|
import {
|
||||||
StartMapInterface
|
StartMapInterface
|
||||||
} from "../../Connection";
|
} from "../../Connexion/ConnexionModels";
|
||||||
import Axios from "axios";
|
import Axios from "axios";
|
||||||
import {API_URL} from "../../Enum/EnvironmentVariable";
|
import {API_URL} from "../../Enum/EnvironmentVariable";
|
||||||
|
import {connectionManager} from "../../Connexion/ConnectionManager";
|
||||||
|
|
||||||
export interface HasMovedEvent {
|
export interface HasMovedEvent {
|
||||||
direction: string;
|
direction: string;
|
||||||
@ -29,13 +30,12 @@ export class GameManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadStartMap() : Promise<StartMapInterface> {
|
loadStartMap() : Promise<StartMapInterface> {
|
||||||
return Axios.get(`${API_URL}/start-map`)
|
return connectionManager.getMapUrlStart().then(mapUrlStart => {
|
||||||
.then((res) => {
|
return {
|
||||||
return res.data;
|
mapUrlStart: mapUrlStart,
|
||||||
}).catch((err) => {
|
startInstance: "global", //todo: is this property still usefull?
|
||||||
console.error(err);
|
}
|
||||||
throw err;
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlayerName(): string {
|
getPlayerName(): string {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import {GameManager, gameManager, HasMovedEvent} from "./GameManager";
|
import {GameManager, gameManager, HasMovedEvent} from "./GameManager";
|
||||||
import {
|
import {
|
||||||
Connection,
|
|
||||||
GroupCreatedUpdatedMessageInterface,
|
GroupCreatedUpdatedMessageInterface,
|
||||||
MessageUserJoined,
|
MessageUserJoined,
|
||||||
MessageUserMovedInterface,
|
MessageUserMovedInterface,
|
||||||
@ -8,7 +7,7 @@ import {
|
|||||||
PointInterface,
|
PointInterface,
|
||||||
PositionInterface,
|
PositionInterface,
|
||||||
RoomJoinedMessageInterface
|
RoomJoinedMessageInterface
|
||||||
} from "../../Connection";
|
} from "../../Connexion/ConnexionModels";
|
||||||
import {CurrentGamerInterface, hasMovedEventName, Player} from "../Player/Player";
|
import {CurrentGamerInterface, hasMovedEventName, Player} from "../Player/Player";
|
||||||
import {DEBUG_MODE, JITSI_URL, POSITION_DELAY, RESOLUTION, ZOOM_LEVEL} from "../../Enum/EnvironmentVariable";
|
import {DEBUG_MODE, JITSI_URL, POSITION_DELAY, RESOLUTION, ZOOM_LEVEL} from "../../Enum/EnvironmentVariable";
|
||||||
import {
|
import {
|
||||||
@ -42,6 +41,8 @@ import {ActionableItem} from "../Items/ActionableItem";
|
|||||||
import {UserInputManager} from "../UserInput/UserInputManager";
|
import {UserInputManager} from "../UserInput/UserInputManager";
|
||||||
import {UserMovedMessage} from "../../Messages/generated/messages_pb";
|
import {UserMovedMessage} from "../../Messages/generated/messages_pb";
|
||||||
import {ProtobufClientUtils} from "../../Network/ProtobufClientUtils";
|
import {ProtobufClientUtils} from "../../Network/ProtobufClientUtils";
|
||||||
|
import {connectionManager} from "../../Connexion/ConnectionManager";
|
||||||
|
import {RoomConnection} from "../../Connexion/RoomConnection";
|
||||||
|
|
||||||
|
|
||||||
export enum Textures {
|
export enum Textures {
|
||||||
@ -100,9 +101,9 @@ export class GameScene extends Phaser.Scene implements CenterListener {
|
|||||||
pendingEvents: Queue<InitUserPositionEventInterface|AddPlayerEventInterface|RemovePlayerEventInterface|UserMovedEventInterface|GroupCreatedUpdatedEventInterface|DeleteGroupEventInterface> = new Queue<InitUserPositionEventInterface|AddPlayerEventInterface|RemovePlayerEventInterface|UserMovedEventInterface|GroupCreatedUpdatedEventInterface|DeleteGroupEventInterface>();
|
pendingEvents: Queue<InitUserPositionEventInterface|AddPlayerEventInterface|RemovePlayerEventInterface|UserMovedEventInterface|GroupCreatedUpdatedEventInterface|DeleteGroupEventInterface> = new Queue<InitUserPositionEventInterface|AddPlayerEventInterface|RemovePlayerEventInterface|UserMovedEventInterface|GroupCreatedUpdatedEventInterface|DeleteGroupEventInterface>();
|
||||||
private initPosition: PositionInterface|null = null;
|
private initPosition: PositionInterface|null = null;
|
||||||
private playersPositionInterpolator = new PlayersPositionInterpolator();
|
private playersPositionInterpolator = new PlayersPositionInterpolator();
|
||||||
private connection!: Connection;
|
private connection!: RoomConnection;
|
||||||
private simplePeer!: SimplePeer;
|
private simplePeer!: SimplePeer;
|
||||||
private connectionPromise!: Promise<Connection>
|
private connectionPromise!: Promise<RoomConnection>
|
||||||
private connectionAnswerPromise: Promise<RoomJoinedMessageInterface>;
|
private connectionAnswerPromise: Promise<RoomJoinedMessageInterface>;
|
||||||
private connectionAnswerPromiseResolve!: (value?: RoomJoinedMessageInterface | PromiseLike<RoomJoinedMessageInterface>) => void;
|
private connectionAnswerPromiseResolve!: (value?: RoomJoinedMessageInterface | PromiseLike<RoomJoinedMessageInterface>) => void;
|
||||||
// A promise that will resolve when the "create" method is called (signaling loading is ended)
|
// A promise that will resolve when the "create" method is called (signaling loading is ended)
|
||||||
@ -202,9 +203,11 @@ export class GameScene extends Phaser.Scene implements CenterListener {
|
|||||||
|
|
||||||
this.load.bitmapFont('main_font', 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
this.load.bitmapFont('main_font', 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml');
|
||||||
|
|
||||||
this.connectionPromise = Connection.createConnection(gameManager.getPlayerName(), gameManager.getCharacterSelected()).then((connection : Connection) => {
|
this.connectionPromise = connectionManager.connectToRoomSocket().then((connection : RoomConnection) => {
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
|
|
||||||
|
this.connection.emitPlayerDetailsMessage(gameManager.getPlayerName(), gameManager.getCharacterSelected())
|
||||||
|
|
||||||
connection.onUserJoins((message: MessageUserJoined) => {
|
connection.onUserJoins((message: MessageUserJoined) => {
|
||||||
const userMessage: AddPlayerInterface = {
|
const userMessage: AddPlayerInterface = {
|
||||||
userId: message.userId,
|
userId: message.userId,
|
||||||
@ -778,7 +781,7 @@ export class GameScene extends Phaser.Scene implements CenterListener {
|
|||||||
this.createCollisionObject();
|
this.createCollisionObject();
|
||||||
|
|
||||||
//join room
|
//join room
|
||||||
this.connectionPromise.then((connection: Connection) => {
|
this.connectionPromise.then((connection: RoomConnection) => {
|
||||||
const camera = this.cameras.main;
|
const camera = this.cameras.main;
|
||||||
connection.joinARoom(this.RoomId,
|
connection.joinARoom(this.RoomId,
|
||||||
this.startX,
|
this.startX,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {HasMovedEvent} from "./GameManager";
|
import {HasMovedEvent} from "./GameManager";
|
||||||
import {MAX_EXTRAPOLATION_TIME} from "../../Enum/EnvironmentVariable";
|
import {MAX_EXTRAPOLATION_TIME} from "../../Enum/EnvironmentVariable";
|
||||||
import {PositionInterface} from "../../Connection";
|
import {PositionInterface} from "../../Connexion/ConnexionModels";
|
||||||
|
|
||||||
export class PlayerMovement {
|
export class PlayerMovement {
|
||||||
public constructor(private startPosition: PositionInterface, private startTick: number, private endPosition: HasMovedEvent, private endTick: number) {
|
public constructor(private startPosition: PositionInterface, private startTick: number, private endPosition: HasMovedEvent, private endTick: number) {
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import {gameManager} from "../Game/GameManager";
|
import {gameManager} from "../Game/GameManager";
|
||||||
import {TextField} from "../Components/TextField";
|
import {TextField} from "../Components/TextField";
|
||||||
import {ClickButton} from "../Components/ClickButton";
|
|
||||||
import Image = Phaser.GameObjects.Image;
|
import Image = Phaser.GameObjects.Image;
|
||||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
|
||||||
import {PLAYER_RESOURCES, PlayerResourceDescriptionInterface} from "../Entity/Character";
|
|
||||||
import {GameSceneInitInterface} from "../Game/GameScene";
|
import {GameSceneInitInterface} from "../Game/GameScene";
|
||||||
import {StartMapInterface} from "../../Connection";
|
import {StartMapInterface} from "../../Connexion/ConnexionModels";
|
||||||
import {mediaManager, MediaManager} from "../../WebRtc/MediaManager";
|
import {mediaManager} from "../../WebRtc/MediaManager";
|
||||||
import {RESOLUTION} from "../../Enum/EnvironmentVariable";
|
import {RESOLUTION} from "../../Enum/EnvironmentVariable";
|
||||||
import {SoundMeter} from "../Components/SoundMeter";
|
import {SoundMeter} from "../Components/SoundMeter";
|
||||||
import {SoundMeterSprite} from "../Components/SoundMeterSprite";
|
import {SoundMeterSprite} from "../Components/SoundMeterSprite";
|
||||||
|
@ -3,8 +3,6 @@ import {TextField} from "../Components/TextField";
|
|||||||
import Image = Phaser.GameObjects.Image;
|
import Image = Phaser.GameObjects.Image;
|
||||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
import Rectangle = Phaser.GameObjects.Rectangle;
|
||||||
import {PLAYER_RESOURCES, PlayerResourceDescriptionInterface} from "../Entity/Character";
|
import {PLAYER_RESOURCES, PlayerResourceDescriptionInterface} from "../Entity/Character";
|
||||||
import {GameSceneInitInterface} from "../Game/GameScene";
|
|
||||||
import {StartMapInterface} from "../../Connection";
|
|
||||||
import {EnableCameraSceneName} from "./EnableCameraScene";
|
import {EnableCameraSceneName} from "./EnableCameraScene";
|
||||||
import {CustomizeSceneName} from "./CustomizeScene";
|
import {CustomizeSceneName} from "./CustomizeScene";
|
||||||
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import {PlayerAnimationNames} from "./Animation";
|
import {PlayerAnimationNames} from "./Animation";
|
||||||
import {GameScene, Textures} from "../Game/GameScene";
|
import {GameScene} from "../Game/GameScene";
|
||||||
import {MessageUserPositionInterface, PointInterface} from "../../Connection";
|
import {UserInputEvent, UserInputManager} from "../UserInput/UserInputManager";
|
||||||
import {ActiveEventList, UserInputEvent, UserInputManager} from "../UserInput/UserInputManager";
|
|
||||||
import {Character} from "../Entity/Character";
|
import {Character} from "../Entity/Character";
|
||||||
import {OutlinePipeline} from "../Shaders/OutlinePipeline";
|
|
||||||
|
|
||||||
|
|
||||||
export const hasMovedEventName = "hasMoved";
|
export const hasMovedEventName = "hasMoved";
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import * as SimplePeerNamespace from "simple-peer";
|
import * as SimplePeerNamespace from "simple-peer";
|
||||||
import {mediaManager} from "./MediaManager";
|
import {mediaManager} from "./MediaManager";
|
||||||
import {Connection} from "../Connection";
|
|
||||||
import {TURN_SERVER, TURN_USER, TURN_PASSWORD} from "../Enum/EnvironmentVariable";
|
import {TURN_SERVER, TURN_USER, TURN_PASSWORD} from "../Enum/EnvironmentVariable";
|
||||||
|
import {RoomConnection} from "../Connexion/RoomConnection";
|
||||||
|
|
||||||
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ export class ScreenSharingPeer extends Peer {
|
|||||||
*/
|
*/
|
||||||
private isReceivingStream:boolean = false;
|
private isReceivingStream:boolean = false;
|
||||||
|
|
||||||
constructor(private userId: number, initiator: boolean, private connection: Connection) {
|
constructor(private userId: number, initiator: boolean, private connection: RoomConnection) {
|
||||||
super({
|
super({
|
||||||
initiator: initiator ? initiator : false,
|
initiator: initiator ? initiator : false,
|
||||||
reconnectTimer: 10000,
|
reconnectTimer: 10000,
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
Connection,
|
|
||||||
WebRtcDisconnectMessageInterface,
|
WebRtcDisconnectMessageInterface,
|
||||||
WebRtcSignalReceivedMessageInterface,
|
WebRtcSignalReceivedMessageInterface,
|
||||||
WebRtcStartMessageInterface
|
WebRtcStartMessageInterface
|
||||||
} from "../Connection";
|
} from "../Connexion/ConnexionModels";
|
||||||
import {
|
import {
|
||||||
mediaManager,
|
mediaManager,
|
||||||
StartScreenSharingCallback,
|
StartScreenSharingCallback,
|
||||||
@ -13,6 +12,7 @@ import {
|
|||||||
import * as SimplePeerNamespace from "simple-peer";
|
import * as SimplePeerNamespace from "simple-peer";
|
||||||
import {ScreenSharingPeer} from "./ScreenSharingPeer";
|
import {ScreenSharingPeer} from "./ScreenSharingPeer";
|
||||||
import {VideoPeer} from "./VideoPeer";
|
import {VideoPeer} from "./VideoPeer";
|
||||||
|
import {RoomConnection} from "../Connexion/RoomConnection";
|
||||||
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
||||||
|
|
||||||
export interface UserSimplePeerInterface{
|
export interface UserSimplePeerInterface{
|
||||||
@ -31,7 +31,7 @@ export interface PeerConnectionListener {
|
|||||||
* This class manages connections to all the peers in the same group as me.
|
* This class manages connections to all the peers in the same group as me.
|
||||||
*/
|
*/
|
||||||
export class SimplePeer {
|
export class SimplePeer {
|
||||||
private Connection: Connection;
|
private Connection: RoomConnection;
|
||||||
private WebRtcRoomId: string;
|
private WebRtcRoomId: string;
|
||||||
private Users: Array<UserSimplePeerInterface> = new Array<UserSimplePeerInterface>();
|
private Users: Array<UserSimplePeerInterface> = new Array<UserSimplePeerInterface>();
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ export class SimplePeer {
|
|||||||
private readonly stopLocalScreenSharingStreamCallback: StopScreenSharingCallback;
|
private readonly stopLocalScreenSharingStreamCallback: StopScreenSharingCallback;
|
||||||
private readonly peerConnectionListeners: Array<PeerConnectionListener> = new Array<PeerConnectionListener>();
|
private readonly peerConnectionListeners: Array<PeerConnectionListener> = new Array<PeerConnectionListener>();
|
||||||
|
|
||||||
constructor(Connection: Connection, WebRtcRoomId: string = "test-webrtc") {
|
constructor(Connection: RoomConnection, WebRtcRoomId: string = "test-webrtc") {
|
||||||
this.Connection = Connection;
|
this.Connection = Connection;
|
||||||
this.WebRtcRoomId = WebRtcRoomId;
|
this.WebRtcRoomId = WebRtcRoomId;
|
||||||
// We need to go through this weird bound function pointer in order to be able to "free" this reference later.
|
// We need to go through this weird bound function pointer in order to be able to "free" this reference later.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import * as SimplePeerNamespace from "simple-peer";
|
import * as SimplePeerNamespace from "simple-peer";
|
||||||
import {mediaManager} from "./MediaManager";
|
import {mediaManager} from "./MediaManager";
|
||||||
import {Connection} from "../Connection";
|
|
||||||
import {TURN_PASSWORD, TURN_SERVER, TURN_USER} from "../Enum/EnvironmentVariable";
|
import {TURN_PASSWORD, TURN_SERVER, TURN_USER} from "../Enum/EnvironmentVariable";
|
||||||
|
import {RoomConnection} from "../Connexion/RoomConnection";
|
||||||
|
|
||||||
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
||||||
|
|
||||||
@ -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: number, initiator: boolean, private connection: Connection) {
|
constructor(private userId: number, initiator: boolean, private connection: RoomConnection) {
|
||||||
super({
|
super({
|
||||||
initiator: initiator ? initiator : false,
|
initiator: initiator ? initiator : false,
|
||||||
reconnectTimer: 10000,
|
reconnectTimer: 10000,
|
||||||
|
@ -11,11 +11,10 @@ import WebGLRenderer = Phaser.Renderer.WebGL.WebGLRenderer;
|
|||||||
import {OutlinePipeline} from "./Phaser/Shaders/OutlinePipeline";
|
import {OutlinePipeline} from "./Phaser/Shaders/OutlinePipeline";
|
||||||
import {CustomizeScene} from "./Phaser/Login/CustomizeScene";
|
import {CustomizeScene} from "./Phaser/Login/CustomizeScene";
|
||||||
import {CoWebsiteManager} from "./WebRtc/CoWebsiteManager";
|
import {CoWebsiteManager} from "./WebRtc/CoWebsiteManager";
|
||||||
import {redirectIfToken} from "./register";
|
import {connectionManager} from "./Connexion/ConnectionManager";
|
||||||
|
|
||||||
//CoWebsiteManager.loadCoWebsite('https://thecodingmachine.com');
|
//CoWebsiteManager.loadCoWebsite('https://thecodingmachine.com');
|
||||||
let connectionData //todo: do something with this data
|
connectionManager.init();
|
||||||
redirectIfToken().then(res => connectionData = res);
|
|
||||||
|
|
||||||
// Load Jitsi if the environment variable is set.
|
// Load Jitsi if the environment variable is set.
|
||||||
if (JITSI_URL) {
|
if (JITSI_URL) {
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
import Axios from "axios";
|
|
||||||
import {API_URL} from "./Enum/EnvironmentVariable";
|
|
||||||
declare let history:History;
|
|
||||||
|
|
||||||
//todo: better naming
|
|
||||||
export interface ConnexionData {
|
|
||||||
organizationSlug: string,
|
|
||||||
worldSlug: string,
|
|
||||||
roomSlug: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function redirectIfToken(): Promise<ConnexionData | null> {
|
|
||||||
const match = /\/register\/(.+)/.exec(window.location.toString());
|
|
||||||
if (!match) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
let res = null;
|
|
||||||
try {
|
|
||||||
res = await Axios.get(`${API_URL}/register/`+match[1])
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const organizationSlug = res.data.organizationSlug;
|
|
||||||
const worldSlug = res.data.worldSlug;
|
|
||||||
const roomSlug = res.data.roomSlug;
|
|
||||||
const connexionUrl = '/@/'+organizationSlug+'/'+worldSlug+'/'+roomSlug;
|
|
||||||
history.pushState({}, '', connexionUrl);
|
|
||||||
return {organizationSlug, worldSlug, roomSlug};
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user