Refactoring Room.ts to fetch map url automatically from ID

This commit is contained in:
David Négrier 2020-10-13 16:46:46 +02:00
parent 0580c692d1
commit aee06da7f9
7 changed files with 94 additions and 56 deletions

View File

@ -25,7 +25,6 @@ import {
RoomJoinedMessage, RoomJoinedMessage,
ItemStateMessage, ItemStateMessage,
ServerToClientMessage, ServerToClientMessage,
SetUserIdMessage,
SilentMessage, SilentMessage,
WebRtcSignalToClientMessage, WebRtcSignalToClientMessage,
WebRtcSignalToServerMessage, WebRtcSignalToServerMessage,
@ -86,7 +85,7 @@ export class IoSocketController {
this.ioConnection(); this.ioConnection();
} }
ioConnection() { ioConnection() {
this.app.ws('/room', { this.app.ws('/room', {
@ -114,7 +113,7 @@ export class IoSocketController {
const websocketExtensions = req.getHeader('sec-websocket-extensions'); const websocketExtensions = req.getHeader('sec-websocket-extensions');
const roomId = query.roomId; const roomId = query.roomId;
//todo: better validation: /\/_\/.*\/.*/ or /\/@\/.*\/.*\/.*/ //todo: better validation: /\/_\/.*\/.*/ or /\/@\/.*\/.*\/.*/
if (typeof roomId !== 'string') { if (typeof roomId !== 'string') {
throw new Error('Undefined room ID: '); throw new Error('Undefined room ID: ');
} }
@ -153,7 +152,7 @@ export class IoSocketController {
throw new Error('Client cannot acces this ressource.') throw new Error('Client cannot acces this ressource.')
} else { } else {
console.log('access granted for user '+userUuid+' and room '+roomId); console.log('access granted for user '+userUuid+' and room '+roomId);
} }
} }
if (upgradeAborted.aborted) { if (upgradeAborted.aborted) {
@ -228,16 +227,6 @@ export class IoSocketController {
// Let's join the room // Let's join the room
this.handleJoinRoom(client, client.roomId, client.position, client.viewport, client.name, client.characterLayers); this.handleJoinRoom(client, client.roomId, client.position, client.viewport, client.name, client.characterLayers);
const setUserIdMessage = new SetUserIdMessage();
setUserIdMessage.setUserid(client.userId);
const serverToClientMessage = new ServerToClientMessage();
serverToClientMessage.setSetuseridmessage(setUserIdMessage);
if (!client.disconnecting) {
client.send(serverToClientMessage.serializeBinary().buffer, true);
}
}, },
message: (ws, arrayBuffer, isBinary): void => { message: (ws, arrayBuffer, isBinary): void => {
const client = ws as ExSocketInterface; const client = ws as ExSocketInterface;
@ -363,6 +352,8 @@ export class IoSocketController {
roomJoinedMessage.addItem(itemStateMessage); roomJoinedMessage.addItem(itemStateMessage);
} }
roomJoinedMessage.setCurrentuserid(client.userId);
const serverToClientMessage = new ServerToClientMessage(); const serverToClientMessage = new ServerToClientMessage();
serverToClientMessage.setRoomjoinedmessage(roomJoinedMessage); serverToClientMessage.setRoomjoinedmessage(roomJoinedMessage);

View File

@ -23,33 +23,33 @@ class ConnectionManager {
const data = await Axios.post(`${API_URL}/register`, {organizationMemberToken}).then(res => res.data); const data = await Axios.post(`${API_URL}/register`, {organizationMemberToken}).then(res => res.data);
this.localUser = new LocalUser(data.userUuid, data.authToken); this.localUser = new LocalUser(data.userUuid, data.authToken);
localUserStore.saveUser(this.localUser); localUserStore.saveUser(this.localUser);
const organizationSlug = data.organizationSlug; const organizationSlug = data.organizationSlug;
const worldSlug = data.worldSlug; const worldSlug = data.worldSlug;
const roomSlug = data.roomSlug; const roomSlug = data.roomSlug;
urlManager.editUrlForRoom(roomSlug, organizationSlug, worldSlug); urlManager.editUrlForRoom(roomSlug, organizationSlug, worldSlug);
const room = new Room(window.location.pathname, data.mapUrlStart) const room = new Room(window.location.pathname);
return Promise.resolve(room); return Promise.resolve(room);
} else if (connexionType === GameConnexionTypes.anonymous) { } else if (connexionType === GameConnexionTypes.anonymous) {
const localUser = localUserStore.getLocalUser(); const localUser = localUserStore.getLocalUser();
if (localUser) { if (localUser && localUser.jwtToken && localUser.uuid) {
this.localUser = localUser this.localUser = localUser
} else { } else {
const data = await Axios.post(`${API_URL}/anonymLogin`).then(res => res.data); const data = await Axios.post(`${API_URL}/anonymLogin`).then(res => res.data);
this.localUser = new LocalUser(data.userUuid, data.authToken); this.localUser = new LocalUser(data.userUuid, data.authToken);
localUserStore.saveUser(this.localUser); localUserStore.saveUser(this.localUser);
} }
const room = new Room(window.location.pathname, urlManager.getAnonymousMapUrlStart()) const room = new Room(window.location.pathname);
return Promise.resolve(room); return Promise.resolve(room);
} else if (connexionType == GameConnexionTypes.organization) { } else if (connexionType == GameConnexionTypes.organization) {
const localUser = localUserStore.getLocalUser(); const localUser = localUserStore.getLocalUser();
if (localUser) { if (localUser) {
this.localUser = localUser this.localUser = localUser
//todo: ask the node api for the correct starting map Url from its slug const room = new Room(window.location.pathname);
return Promise.reject('Case not handled: need to get the map\'s url from its slug'); return Promise.resolve(room);
} else { } else {
//todo: find some kind of fallback? //todo: find some kind of fallback?
return Promise.reject('Could not find a user in localstorage'); return Promise.reject('Could not find a user in localstorage');

View File

@ -1,10 +1,67 @@
import Axios from "axios";
import {API_URL} from "../Enum/EnvironmentVariable";
export class Room { export class Room {
public ID: string; public readonly id: string;
public url: string public readonly isPublic: boolean;
private mapUrl: string|undefined;
constructor(ID: string, url: string) { //public url: string
this.ID = ID;
this.url = url; constructor(id: string/*, url: string*/) {
if (id.startsWith('/')) {
id = id.substr(1);
}
this.id = id;
if (id.startsWith('_/')) {
this.isPublic = true;
} else if (id.startsWith('@/')) {
this.isPublic = false;
} else {
throw new Error('Invalid room ID');
}
} }
} public async getMapUrl(): Promise<string> {
return new Promise<string>(async (resolve, reject) => {
if (this.mapUrl !== undefined) {
resolve(this.mapUrl);
return;
}
if (this.isPublic) {
const match = /_\/[^\/]+\/(.+)/.exec(this.id)
if (!match) throw new Error('Could not extract url from "'+this.id+'"');
this.mapUrl = window.location.protocol+'//'+match[1];
resolve(this.mapUrl);
return;
} else {
// We have a private ID, we need to query the map URL from the server.
const urlParts = this.parsePrivateUrl(this.id);
const data:any = await Axios.get(`${API_URL}/map`, {
params: urlParts
});
console.log('Map ', this.id, ' resolves to URL ', data.data.mapUrl);
resolve(data.data.mapUrl);
return;
}
});
}
private parsePrivateUrl(url: string): { organizationSlug: string, worldSlug: string, roomSlug?: string } {
const regex = /@\/([^\/]+)\/([^\/]+)(?:\/([^\/]*))?/gm;
const match = regex.exec(url);
if (!match) {
throw new Error('Invalid URL '+url);
}
let results: { organizationSlug: string, worldSlug: string, roomSlug?: string } = {
organizationSlug: match[1],
worldSlug: match[2],
}
if (match[3] !== undefined) {
results.roomSlug = match[3];
}
return results;
}
}

View File

@ -11,7 +11,6 @@ import {
RoomJoinedMessage, RoomJoinedMessage,
ServerToClientMessage, ServerToClientMessage,
SetPlayerDetailsMessage, SetPlayerDetailsMessage,
SetUserIdMessage,
SilentMessage, StopGlobalMessage, SilentMessage, StopGlobalMessage,
UserJoinedMessage, UserJoinedMessage,
UserLeftMessage, UserLeftMessage,
@ -58,7 +57,7 @@ export class RoomConnection implements RoomConnection {
let url = API_URL.replace('http://', 'ws://').replace('https://', 'wss://'); let url = API_URL.replace('http://', 'ws://').replace('https://', 'wss://');
url += '/room'; url += '/room';
url += '?roomId='+(roomId ?encodeURIComponent(roomId):''); url += '?roomId='+(roomId ?encodeURIComponent(roomId):'');
url += '?token='+(token ?encodeURIComponent(token):''); url += '&token='+(token ?encodeURIComponent(token):'');
url += '&name='+encodeURIComponent(name); url += '&name='+encodeURIComponent(name);
for (const layer of characterLayers) { for (const layer of characterLayers) {
url += '&characterLayers='+encodeURIComponent(layer); url += '&characterLayers='+encodeURIComponent(layer);
@ -124,13 +123,13 @@ export class RoomConnection implements RoomConnection {
items[item.getItemid()] = JSON.parse(item.getStatejson()); items[item.getItemid()] = JSON.parse(item.getStatejson());
} }
this.userId = roomJoinedMessage.getCurrentuserid();
this.dispatch(EventMessage.START_ROOM, { this.dispatch(EventMessage.START_ROOM, {
users, users,
groups, groups,
items items
}); });
} else if (message.hasSetuseridmessage()) {
this.userId = (message.getSetuseridmessage() as SetUserIdMessage).getUserid();
} else if (message.hasErrormessage()) { } else if (message.hasErrormessage()) {
console.error(EventMessage.MESSAGE_ERROR, message.getErrormessage()?.getMessage()); console.error(EventMessage.MESSAGE_ERROR, message.getErrormessage()?.getMessage());
} else if (message.hasWebrtcsignaltoclientmessage()) { } else if (message.hasWebrtcsignaltoclientmessage()) {

View File

@ -17,7 +17,8 @@ export class GameManager {
public async init(scenePlugin: Phaser.Scenes.ScenePlugin) { public async init(scenePlugin: Phaser.Scenes.ScenePlugin) {
this.startRoom = await connectionManager.initGameConnexion(); this.startRoom = await connectionManager.initGameConnexion();
this.loadMap(this.startRoom.url, this.startRoom.ID, scenePlugin); const url = await this.startRoom.getMapUrl();
this.loadMap(url, this.startRoom.id, scenePlugin);
} }
public setPlayerName(name: string): void { public setPlayerName(name: string): void {
@ -58,9 +59,10 @@ export class GameManager {
return mapUrlStart.substring(startPos, endPos); return mapUrlStart.substring(startPos, endPos);
} }
public goToStartingMap(scenePlugin: Phaser.Scenes.ScenePlugin) { public async goToStartingMap(scenePlugin: Phaser.Scenes.ScenePlugin) {
console.log('Starting scene '+this.startRoom.url); const url = await this.startRoom.getMapUrl();
scenePlugin.start(this.startRoom.url, {startLayerName: 'global'}); console.log('Starting scene '+url);
scenePlugin.start(url, {startLayerName: 'global'});
} }
} }

View File

@ -23,13 +23,6 @@ class UrlManager {
} }
} }
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 window.location.protocol+'//'+match[1];
}
public getOrganizationToken(): string|null { public getOrganizationToken(): string|null {
const match = /\/register\/(.+)/.exec(window.location.pathname.toString()); const match = /\/register\/(.+)/.exec(window.location.pathname.toString());
return match ? match [1] : null; return match ? match [1] : null;

View File

@ -129,10 +129,6 @@ message ErrorMessage {
string message = 1; string message = 1;
} }
message SetUserIdMessage {
int32 userId = 1;
}
message ItemStateMessage { message ItemStateMessage {
int32 itemId = 1; int32 itemId = 1;
string stateJson = 2; string stateJson = 2;
@ -142,6 +138,7 @@ message RoomJoinedMessage {
repeated UserJoinedMessage user = 1; repeated UserJoinedMessage user = 1;
repeated GroupUpdateMessage group = 2; repeated GroupUpdateMessage group = 2;
repeated ItemStateMessage item = 3; repeated ItemStateMessage item = 3;
int32 currentUserId = 4;
} }
message WebRtcStartMessage { message WebRtcStartMessage {
@ -164,12 +161,11 @@ message ServerToClientMessage {
BatchMessage batchMessage = 1; BatchMessage batchMessage = 1;
ErrorMessage errorMessage = 2; ErrorMessage errorMessage = 2;
RoomJoinedMessage roomJoinedMessage = 3; RoomJoinedMessage roomJoinedMessage = 3;
SetUserIdMessage setUserIdMessage = 4; // TODO: merge this with RoomJoinedMessage ? WebRtcStartMessage webRtcStartMessage = 4;
WebRtcStartMessage webRtcStartMessage = 5; WebRtcSignalToClientMessage webRtcSignalToClientMessage = 5;
WebRtcSignalToClientMessage webRtcSignalToClientMessage = 6; WebRtcSignalToClientMessage webRtcScreenSharingSignalToClientMessage = 6;
WebRtcSignalToClientMessage webRtcScreenSharingSignalToClientMessage = 7; WebRtcDisconnectMessage webRtcDisconnectMessage = 7;
WebRtcDisconnectMessage webRtcDisconnectMessage = 8; PlayGlobalMessage playGlobalMessage = 8;
PlayGlobalMessage playGlobalMessage = 9; StopGlobalMessage stopGlobalMessage = 9;
StopGlobalMessage stopGlobalMessage = 10;
} }
} }