From 02c193a262422d2ac90442f00f390d13be5b4788 Mon Sep 17 00:00:00 2001 From: arp Date: Mon, 12 Oct 2020 16:23:07 +0200 Subject: [PATCH] rewrote the authorisation flow: give more responsability to gameManager and less to gameScene --- back/src/Controller/AuthenticateController.ts | 76 ++++++++------- back/src/Controller/IoSocketController.ts | 24 +++-- back/src/Model/RoomIdentifier.ts | 14 +++ back/src/Services/AdminApi.ts | 8 +- front/src/Connexion/ConnectionManager.ts | 94 ++++++++++--------- front/src/Connexion/LocalUser.ts | 9 ++ front/src/Connexion/LocalUserStore.ts | 16 ++++ front/src/Connexion/Room.ts | 10 ++ front/src/Connexion/RoomConnection.ts | 3 +- front/src/Phaser/Game/GameManager.ts | 77 ++++----------- front/src/Phaser/Game/GameScene.ts | 23 +---- front/src/Phaser/Login/EnableCameraScene.ts | 3 +- front/src/Url/UrlManager.ts | 52 ++++++++++ front/src/index.ts | 5 +- 14 files changed, 244 insertions(+), 170 deletions(-) create mode 100644 back/src/Model/RoomIdentifier.ts create mode 100644 front/src/Connexion/LocalUser.ts create mode 100644 front/src/Connexion/LocalUserStore.ts create mode 100644 front/src/Connexion/Room.ts create mode 100644 front/src/Url/UrlManager.ts diff --git a/back/src/Controller/AuthenticateController.ts b/back/src/Controller/AuthenticateController.ts index 984d7445..55036a0e 100644 --- a/back/src/Controller/AuthenticateController.ts +++ b/back/src/Controller/AuthenticateController.ts @@ -1,8 +1,7 @@ -import {URL_ROOM_STARTED} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..." import { v4 } from 'uuid'; import {HttpRequest, HttpResponse, TemplatedApp} from "uWebSockets.js"; import {BaseController} from "./BaseController"; -import {adminApi, AdminApiData} from "../Services/AdminApi"; +import {adminApi} from "../Services/AdminApi"; import {jwtTokenManager} from "../Services/JWTTokenManager"; export interface TokenInterface { @@ -13,18 +12,19 @@ export class AuthenticateController extends BaseController { constructor(private App : TemplatedApp) { super(); - this.login(); + this.register(); + this.anonymLogin(); } - //permit to login on application. Return token to connect on Websocket IO. - login(){ - this.App.options("/login", (res: HttpResponse, req: HttpRequest) => { + //Try to login with an admin token + register(){ + this.App.options("/register", (res: HttpResponse, req: HttpRequest) => { this.addCorsHeaders(res); res.end(); }); - this.App.post("/login", (res: HttpResponse, req: HttpRequest) => { + this.App.post("/register", (res: HttpResponse, req: HttpRequest) => { (async () => { this.addCorsHeaders(res); @@ -36,35 +36,25 @@ export class AuthenticateController extends BaseController { //todo: what to do if the organizationMemberToken is already used? const organizationMemberToken:string|null = param.organizationMemberToken; - const mapSlug:string|null = param.mapSlug; - + try { - let userUuid; - let mapUrlStart; - let newUrl: string|null = null; + if (typeof organizationMemberToken != 'string') throw new Error('No organization token'); + const data = await adminApi.fetchMemberDataByToken(organizationMemberToken); - if (organizationMemberToken) { - const data = await adminApi.fetchMemberDataByToken(organizationMemberToken); - - userUuid = data.userUuid; - mapUrlStart = data.mapUrlStart; - newUrl = this.getNewUrlOnAdminAuth(data) - } else if (mapSlug !== null) { - userUuid = v4(); - mapUrlStart = mapSlug; - newUrl = null; - } else { - userUuid = v4(); - mapUrlStart = host.replace('api.', 'maps.') + URL_ROOM_STARTED; - newUrl = '_/global/'+mapUrlStart; - } + const userUuid = data.userUuid; + const organizationSlug = data.organizationSlug; + const worldSlug = data.worldSlug; + const roomSlug = data.roomSlug; + const mapUrlStart = data.mapUrlStart; const authToken = jwtTokenManager.createJWTToken(userUuid); res.writeStatus("200 OK").end(JSON.stringify({ authToken, userUuid, + organizationSlug, + worldSlug, + roomSlug, mapUrlStart, - newUrl, })); } catch (e) { @@ -75,12 +65,32 @@ export class AuthenticateController extends BaseController { })(); }); + } - private getNewUrlOnAdminAuth(data:AdminApiData): string { - const organizationSlug = data.organizationSlug; - const worldSlug = data.worldSlug; - const roomSlug = data.roomSlug; - return '/@/'+organizationSlug+'/'+worldSlug+'/'+roomSlug; + //permit to login on application. Return token to connect on Websocket IO. + anonymLogin(){ + this.App.options("/anonymLogin", (res: HttpResponse, req: HttpRequest) => { + this.addCorsHeaders(res); + + res.end(); + }); + + this.App.post("/anonymLogin", (res: HttpResponse, req: HttpRequest) => { + (async () => { + this.addCorsHeaders(res); + + res.onAborted(() => { + console.warn('Login request was aborted'); + }) + + const userUuid = v4(); + const authToken = jwtTokenManager.createJWTToken(userUuid); + res.writeStatus("200 OK").end(JSON.stringify({ + authToken, + userUuid, + })); + })(); + }); } } diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index 7ef0d811..306b874e 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -42,6 +42,7 @@ import {cpuTracker} from "../Services/CpuTracker"; import {ViewportInterface} from "../Model/Websocket/ViewportMessage"; import {jwtTokenManager} from "../Services/JWTTokenManager"; import {adminApi} from "../Services/AdminApi"; +import {RoomIdentifier} from "../Model/RoomIdentifier"; function emitInBatch(socket: ExSocketInterface, payload: SubMessage): void { socket.batchedMessages.addPayload(payload); @@ -88,7 +89,7 @@ export class IoSocketController { ioConnection() { - this.app.ws('/room/*', { + this.app.ws('/room', { /* Options */ //compression: uWS.SHARED_COMPRESSOR, maxPayloadLength: 16 * 1024 * 1024, @@ -112,7 +113,12 @@ export class IoSocketController { const websocketProtocol = req.getHeader('sec-websocket-protocol'); const websocketExtensions = req.getHeader('sec-websocket-extensions'); - const roomId = req.getUrl().substr(6); + const roomId = query.roomId; + //todo: better validation: /\/_\/.*\/.*/ or /\/@\/.*\/.*\/.*/ + if (typeof roomId !== 'string') { + throw new Error('Undefined room ID: '); + } + const roomIdentifier = new RoomIdentifier(roomId); const token = query.token; const x = Number(query.x); @@ -140,12 +146,14 @@ export class IoSocketController { const userUuid = await jwtTokenManager.getUserUuidFromToken(token); console.log('uuid', userUuid); - const isGranted = await adminApi.memberIsGrantedAccessToRoom(userUuid, roomId); - if (!isGranted) { - console.log('access not granted for user '+userUuid+' and room '+roomId); - throw new Error('Client cannot acces this ressource.') - } else { - console.log('access granted for user '+userUuid+' and room '+roomId); + if (roomIdentifier.anonymous === false) { + const isGranted = await adminApi.memberIsGrantedAccessToRoom(userUuid, roomIdentifier); + if (!isGranted) { + console.log('access not granted for user '+userUuid+' and room '+roomId); + throw new Error('Client cannot acces this ressource.') + } else { + console.log('access granted for user '+userUuid+' and room '+roomId); + } } if (upgradeAborted.aborted) { diff --git a/back/src/Model/RoomIdentifier.ts b/back/src/Model/RoomIdentifier.ts new file mode 100644 index 00000000..9bb58bb9 --- /dev/null +++ b/back/src/Model/RoomIdentifier.ts @@ -0,0 +1,14 @@ +export class RoomIdentifier { + public anonymous: boolean; + public id:string + constructor(roomID: string) { + if (roomID.indexOf('_/') === 0) { + this.anonymous = true; + } else if(roomID.indexOf('@/') === 0) { + this.anonymous = false; + } else { + throw new Error('Incorrect room ID: '+roomID); + } + this.id = roomID; //todo: extract more data from the id (like room slug, organization name, etc); + } +} \ No newline at end of file diff --git a/back/src/Services/AdminApi.ts b/back/src/Services/AdminApi.ts index 79a68810..2d03ee9d 100644 --- a/back/src/Services/AdminApi.ts +++ b/back/src/Services/AdminApi.ts @@ -1,5 +1,6 @@ import {ADMIN_API_TOKEN, ADMIN_API_URL} from "../Enum/EnvironmentVariable"; -import Axios, {AxiosError} from "axios"; +import Axios from "axios"; +import {RoomIdentifier} from "../Model/RoomIdentifier"; export interface AdminApiData { organizationSlug: string @@ -22,13 +23,14 @@ class AdminApi { return res.data; } - async memberIsGrantedAccessToRoom(memberId: string, roomId: string): Promise { + async memberIsGrantedAccessToRoom(memberId: string, roomIdentifier: RoomIdentifier): Promise { if (!ADMIN_API_URL) { return Promise.reject('No admin backoffice set!'); } try { + //todo: send more specialized data instead of the whole id const res = await Axios.get(ADMIN_API_URL+'/api/member/is-granted-access', - { headers: {"Authorization" : `${ADMIN_API_TOKEN}`}, params: {memberId, roomIdentifier: roomId} } + { headers: {"Authorization" : `${ADMIN_API_TOKEN}`}, params: {memberId, roomIdentifier: roomIdentifier.id} } ) return !!res.data; } catch (e) { diff --git a/front/src/Connexion/ConnectionManager.ts b/front/src/Connexion/ConnectionManager.ts index 91a42882..0fea50b5 100644 --- a/front/src/Connexion/ConnectionManager.ts +++ b/front/src/Connexion/ConnectionManager.ts @@ -2,54 +2,67 @@ import Axios from "axios"; import {API_URL} from "../Enum/EnvironmentVariable"; import {RoomConnection} from "./RoomConnection"; import {PositionInterface, ViewportInterface} from "./ConnexionModels"; - -interface LoginApiData { - authToken: string - userUuid: string - mapUrlStart: string - newUrl: string -} +import {GameConnexionTypes, urlManager} from "../Url/UrlManager"; +import {localUserStore} from "./LocalUserStore"; +import {LocalUser} from "./LocalUser"; +import {Room} from "./Room"; class ConnectionManager { - private initPromise!: Promise; - private mapUrlStart: string|null = null; + private localUser!:LocalUser; - private authToken:string|null = null; - private userUuid: string|null = null; + /** + * Tries to login to the node server and return the starting map url to be loaded + */ + public async initGameConnexion(): Promise { - //todo: get map infos from url in anonym case - public async init(): Promise { - let organizationMemberToken = null; - let teamSlug = null; - let mapSlug = null; - const match = /\/register\/(.+)/.exec(window.location.toString()); - if (match) { - organizationMemberToken = match[1]; - } else { - const match = /\/_\/(.+)\/(.+)/.exec(window.location.toString()); - teamSlug = match ? match[1] : null; - mapSlug = match ? match[2] : null; - } - this.initPromise = Axios.post(`${API_URL}/login`, {organizationMemberToken, teamSlug, mapSlug}).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; - console.log('u', this.userUuid) - - if (newUrl) { - history.pushState({}, '', newUrl); + const connexionType = urlManager.getGameConnexionType(); + if(connexionType === GameConnexionTypes.register) { + const organizationMemberToken = urlManager.getOrganizationToken(); + const data:any = await Axios.post(`${API_URL}/register`, {organizationMemberToken}).then(res => res.data); + this.localUser = new LocalUser(data.userUuid, data.authToken); + localUserStore.saveUser(this.localUser); + + const organizationSlug = data.organizationSlug; + const worldSlug = data.worldSlug; + const roomSlug = data.roomSlug; + urlManager.editUrlForRoom(roomSlug, organizationSlug, worldSlug); + + const room = new Room(window.location.pathname, data.mapUrlStart) + return Promise.resolve(room); + } else if (connexionType === GameConnexionTypes.anonymous) { + const localUser = localUserStore.getLocalUser(); + + if (localUser) { + this.localUser = localUser + } else { + const data:any = await Axios.post(`${API_URL}/anonymLogin`).then(res => res.data); + this.localUser = new LocalUser(data.userUuid, data.authToken); + localUserStore.saveUser(this.localUser); + } + const room = new Room(window.location.pathname, urlManager.getAnonymousMapUrlStart()) + return Promise.resolve(room); + } else if (connexionType == GameConnexionTypes.organization) { + const localUser = localUserStore.getLocalUser(); + + if (localUser) { + this.localUser = localUser + //todo: ask the node api for the correct starting map Url from its slug + return Promise.reject('Case not handled: need to get the map\'s url from its slug'); + } else { + //todo: find some kind of fallback? + return Promise.reject('Could not find a user in localstorage'); + } } + return Promise.reject('ConnexionManager initialization failed'); } public initBenchmark(): void { - this.authToken = 'test'; + this.localUser = new LocalUser('', 'test'); } public connectToRoomSocket(roomId: string, name: string, characterLayers: string[], position: PositionInterface, viewport: ViewportInterface): Promise { return new Promise((resolve, reject) => { - const connection = new RoomConnection(this.authToken, roomId, name, characterLayers, position, viewport); + const connection = new RoomConnection(this.localUser.jwtToken, roomId, name, characterLayers, position, viewport); connection.onConnectError((error: object) => { console.log('An error occurred while connecting to socket server. Retrying'); reject(error); @@ -67,15 +80,6 @@ class ConnectionManager { }); }); } - - public getMapUrlStart(): Promise { - return this.initPromise.then(() => { - if (!this.mapUrlStart) { - throw new Error('No map url set!'); - } - return this.mapUrlStart; - }) - } } export const connectionManager = new ConnectionManager(); diff --git a/front/src/Connexion/LocalUser.ts b/front/src/Connexion/LocalUser.ts new file mode 100644 index 00000000..1411f66c --- /dev/null +++ b/front/src/Connexion/LocalUser.ts @@ -0,0 +1,9 @@ +export class LocalUser { + public uuid: string; + public jwtToken: string; + + constructor(uuid:string, jwtToken: string) { + this.uuid = uuid; + this.jwtToken = jwtToken; + } +} \ No newline at end of file diff --git a/front/src/Connexion/LocalUserStore.ts b/front/src/Connexion/LocalUserStore.ts new file mode 100644 index 00000000..0976b5c9 --- /dev/null +++ b/front/src/Connexion/LocalUserStore.ts @@ -0,0 +1,16 @@ +import {LocalUser} from "./LocalUser"; + +class LocalUserStore { + + saveUser(localUser: LocalUser) { + localStorage.setItem('localUser', JSON.stringify(localUser)); + } + + getLocalUser(): LocalUser|null { + const data = localStorage.getItem('localUser'); + return data ? JSON.parse(data) : null; + } + +} + +export const localUserStore = new LocalUserStore(); \ No newline at end of file diff --git a/front/src/Connexion/Room.ts b/front/src/Connexion/Room.ts new file mode 100644 index 00000000..36a8072b --- /dev/null +++ b/front/src/Connexion/Room.ts @@ -0,0 +1,10 @@ +export class Room { + public ID: string; + public url: string + + constructor(ID: string, url: string) { + this.ID = ID; + this.url = url; + } + +} \ No newline at end of file diff --git a/front/src/Connexion/RoomConnection.ts b/front/src/Connexion/RoomConnection.ts index ed669fed..fd9410c4 100644 --- a/front/src/Connexion/RoomConnection.ts +++ b/front/src/Connexion/RoomConnection.ts @@ -56,7 +56,8 @@ export class RoomConnection implements RoomConnection { */ public constructor(token: string|null, roomId: string, name: string, characterLayers: string[], position: PositionInterface, viewport: ViewportInterface) { let url = API_URL.replace('http://', 'ws://').replace('https://', 'wss://'); - url += '/room/'+roomId + url += '/room'; + url += '?roomId='+(roomId ?encodeURIComponent(roomId):''); url += '?token='+(token ?encodeURIComponent(token):''); url += '&name='+encodeURIComponent(name); for (const layer of characterLayers) { diff --git a/front/src/Phaser/Game/GameManager.ts b/front/src/Phaser/Game/GameManager.ts index 5188d2fe..10277e20 100644 --- a/front/src/Phaser/Game/GameManager.ts +++ b/front/src/Phaser/Game/GameManager.ts @@ -1,10 +1,6 @@ -import {GameScene, GameSceneInitInterface} from "./GameScene"; -import { - StartMapInterface -} from "../../Connexion/ConnexionModels"; -import Axios from "axios"; -import {API_URL} from "../../Enum/EnvironmentVariable"; +import {GameScene} from "./GameScene"; import {connectionManager} from "../../Connexion/ConnectionManager"; +import {Room} from "../../Connexion/Room"; export interface HasMovedEvent { direction: string; @@ -13,14 +9,17 @@ export interface HasMovedEvent { y: number; } -export interface loadMapResponseInterface { - key: string, - startLayerName: string; -} - export class GameManager { private playerName!: string; private characterLayers!: string[]; + private startRoom!:Room; + private sceneManager!: Phaser.Scenes.SceneManager; + + public async init(sceneManager: Phaser.Scenes.SceneManager) { + this.sceneManager = sceneManager; + this.startRoom = await connectionManager.initGameConnexion(); + this.loadMap(this.startRoom.url, this.startRoom.ID); + } public setPlayerName(name: string): void { this.playerName = name; @@ -41,55 +40,15 @@ export class GameManager { getCharacterSelected(): string[] { return this.characterLayers; } - - /** - * Returns the map URL and the instance from the current URL - */ - private findMapUrl(): [string, string]|null { - const path = window.location.pathname; - if (!path.startsWith('/_/')) { - return null; - } - const instanceAndMap = path.substr(3); - const firstSlash = instanceAndMap.indexOf('/'); - if (firstSlash === -1) { - return null; - } - const instance = instanceAndMap.substr(0, firstSlash); - return [window.location.protocol+'//'+instanceAndMap.substr(firstSlash+1), instance]; - } - public loadStartingMap(scene: Phaser.Scenes.ScenePlugin): Promise { - // Do we have a start URL in the address bar? If so, let's redirect to this address - const instanceAndMapUrl = this.findMapUrl(); - if (instanceAndMapUrl !== null) { - const [mapUrl, instance] = instanceAndMapUrl; - const key = gameManager.loadMap(mapUrl, scene, instance); - const startLayerName = window.location.hash ? window.location.hash.substr(1) : ''; - return Promise.resolve({key, startLayerName}); - - } else { - // If we do not have a map address in the URL, let's ask the server for a start map. - return connectionManager.getMapUrlStart().then((mapUrlStart: string) => { - const key = gameManager.loadMap(window.location.protocol + "//" + mapUrlStart, scene, 'global'); - return {key, startLayerName: ''} - }).catch((err) => { - console.error(err); - throw err; - }); - } - - } - - public loadMap(mapUrl: string, scene: Phaser.Scenes.ScenePlugin, instance: string): string { - const sceneKey = this.getMapKeyByUrl(mapUrl); - - const gameIndex = scene.getIndex(sceneKey); + + public loadMap(mapUrl: string, roomID: string): void { + console.log('Loading map '+roomID+' at url '+mapUrl); + const gameIndex = this.sceneManager.getIndex(roomID); if(gameIndex === -1){ - const game : Phaser.Scene = GameScene.createFromUrl(mapUrl, instance); - scene.add(sceneKey, game, false); + const game : Phaser.Scene = GameScene.createFromUrl(mapUrl, roomID); + this.sceneManager.add(roomID, game, false); } - return sceneKey; } public getMapKeyByUrl(mapUrlStart: string) : string { @@ -98,6 +57,10 @@ export class GameManager { const endPos = mapUrlStart.indexOf(".json"); return mapUrlStart.substring(startPos, endPos); } + + public async goToStartingMap() { + this.sceneManager.start(this.startRoom.ID, {startLayerName: 'global'}); + } } export const gameManager = new GameManager(); diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index ba1d75fa..602f697e 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -418,15 +418,7 @@ export class GameScene extends ResizableScene implements CenterListener { context.strokeStyle = '#ffffff'; context.stroke(); this.circleTexture.refresh(); - - // Let's alter browser history - const url = new URL(this.MapUrlFile); - let path = '/_/'+this.instance+'/'+url.host+url.pathname; - if (this.startLayerName) { - path += '#'+this.startLayerName; - } - window.history.pushState({}, 'WorkAdventure', path); - + // Let's pause the scene if the connection is not established yet if (this.connection === undefined) { // Let's wait 0.5 seconds before printing the "connecting" screen to avoid blinking @@ -686,6 +678,7 @@ export class GameScene extends ResizableScene implements CenterListener { * @param tileWidth * @param tileHeight */ + //todo: push that into the gameManager private loadNextGame(layer: ITiledMapLayer, mapWidth: number, tileWidth: number, tileHeight: number){ const exitSceneUrl = this.getExitSceneUrl(layer); if (exitSceneUrl === undefined) { @@ -698,7 +691,8 @@ export class GameScene extends ResizableScene implements CenterListener { // TODO: eventually compute a relative URL const absoluteExitSceneUrl = new URL(exitSceneUrl, this.MapUrlFile).href; - const exitSceneKey = gameManager.loadMap(absoluteExitSceneUrl, this.scene, instance); + gameManager.loadMap(absoluteExitSceneUrl, instance); + const exitSceneKey = instance; const tiles : number[] = layer.data as number[]; for (let key=0; key < tiles.length; key++) { @@ -785,14 +779,6 @@ export class GameScene extends ResizableScene implements CenterListener { }); } - createCollisionObject(){ - /*this.Objects.forEach((Object : Phaser.Physics.Arcade.Sprite) => { - this.physics.add.collider(this.CurrentPlayer, Object, (object1, object2) => { - this.CurrentPlayer.say("Collision with object : " + (object2 as Phaser.Physics.Arcade.Sprite).texture.key) - }); - })*/ - } - createCurrentPlayer(){ //initialise player //TODO create animation moving between exit and start @@ -809,7 +795,6 @@ export class GameScene extends ResizableScene implements CenterListener { //create collision this.createCollisionWithPlayer(); - this.createCollisionObject(); } pushPlayerPosition(event: HasMovedEvent) { diff --git a/front/src/Phaser/Login/EnableCameraScene.ts b/front/src/Phaser/Login/EnableCameraScene.ts index 5d5339d9..8695464b 100644 --- a/front/src/Phaser/Login/EnableCameraScene.ts +++ b/front/src/Phaser/Login/EnableCameraScene.ts @@ -266,8 +266,7 @@ export class EnableCameraScene extends Phaser.Scene { mediaManager.stopCamera(); mediaManager.stopMicrophone(); - const {key, startLayerName} = await gameManager.loadStartingMap(this.scene); - this.scene.start(key, {startLayerName}); + gameManager.goToStartingMap(); } private async getDevices() { diff --git a/front/src/Url/UrlManager.ts b/front/src/Url/UrlManager.ts new file mode 100644 index 00000000..39f5667d --- /dev/null +++ b/front/src/Url/UrlManager.ts @@ -0,0 +1,52 @@ + +export enum GameConnexionTypes { + anonymous=1, + organization, + register, + unknown, +} + +//this class is responsible with analysing and editing the game's url +class UrlManager { + + //todo: use that to detect if we can find a token in localstorage + public getGameConnexionType(): GameConnexionTypes { + const url = window.location.pathname.toString(); + if (url.indexOf('_/') > -1) { + return GameConnexionTypes.anonymous; + } else if (url.indexOf('@/') > -1) { + return GameConnexionTypes.organization; + } else if(url.indexOf('register/')) { + return GameConnexionTypes.register + } else { + return GameConnexionTypes.unknown + } + } + + public getAnonymousMapUrlStart():string { + const match = /\/_\/global\/(.+)/.exec(window.location.pathname.toString()) + if (!match) throw new Error('Could not extract startmap url from'+window.location.pathname); + return match[1]; + + } + + public getOrganizationToken(): string|null { + const match = /\/register\/(.+)/.exec(window.location.pathname.toString()); + return match ? match [1] : null; + } + + + public editUrlForRoom(roomSlug: string, organizationSlug: string|null, worldSlug: string |null): string { + let newUrl:string; + if (organizationSlug) { + newUrl = '/@/'+organizationSlug+'/'+worldSlug+'/'+roomSlug; + } else { + newUrl = '/_/global/'+roomSlug; + } + history.pushState({}, 'WorkAdventure', newUrl); + return newUrl; + } + +} + +export const urlManager = new UrlManager(); \ No newline at end of file diff --git a/front/src/index.ts b/front/src/index.ts index 177c56c0..f57474d7 100644 --- a/front/src/index.ts +++ b/front/src/index.ts @@ -11,11 +11,10 @@ import WebGLRenderer = Phaser.Renderer.WebGL.WebGLRenderer; import {OutlinePipeline} from "./Phaser/Shaders/OutlinePipeline"; import {CustomizeScene} from "./Phaser/Login/CustomizeScene"; import {CoWebsiteManager} from "./WebRtc/CoWebsiteManager"; -import {connectionManager} from "./Connexion/ConnectionManager"; +import {gameManager} from "./Phaser/Game/GameManager"; import {ResizableScene} from "./Phaser/Login/ResizableScene"; //CoWebsiteManager.loadCoWebsite('https://thecodingmachine.com'); -connectionManager.init(); // Load Jitsi if the environment variable is set. if (JITSI_URL) { @@ -52,6 +51,8 @@ cypressAsserter.gameStarted(); const game = new Phaser.Game(config); +gameManager.init(game.scene); + window.addEventListener('resize', function (event) { const {width, height} = CoWebsiteManager.getGameSize();