diff --git a/front/src/Connexion/Room.ts b/front/src/Connexion/Room.ts index d9bfe905..72c3b42e 100644 --- a/front/src/Connexion/Room.ts +++ b/front/src/Connexion/Room.ts @@ -25,7 +25,7 @@ export class Room { this.id = this.id.substr(0, indexOfHash); } } - + public static getIdFromIdentifier(identifier: string, baseUrl: string, currentInstance: string): {roomId: string, hash: string} { let roomId = ''; let hash = ''; @@ -72,8 +72,9 @@ export class Room { console.log('Map ', this.id, ' resolves to URL ', data.mapUrl); resolve(data.mapUrl); return; + }).catch((reason) => { + reject(reason); }); - } }); } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index d25c2893..c2cb0950 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -45,7 +45,6 @@ import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR; import {GameMap} from "./GameMap"; import {coWebsiteManager} from "../../WebRtc/CoWebsiteManager"; import {mediaManager} from "../../WebRtc/MediaManager"; -import {FourOFourSceneName} from "../Reconnecting/FourOFourScene"; import {ItemFactoryInterface} from "../Items/ItemFactoryInterface"; import {ActionableItem} from "../Items/ActionableItem"; import {UserInputManager} from "../UserInput/UserInputManager"; @@ -67,6 +66,7 @@ import {OpenChatIcon, openChatIconName} from "../Components/OpenChatIcon"; import {SelectCharacterScene, SelectCharacterSceneName} from "../Login/SelectCharacterScene"; import {TextureError} from "../../Exception/TextureError"; import {addLoader} from "../Components/Loader"; +import {ErrorSceneName} from "../Reconnecting/ErrorScene"; export interface GameSceneInitInterface { initPosition: PointInterface|null, @@ -185,8 +185,10 @@ export class GameScene extends ResizableScene implements CenterListener { this.load.image(openChatIconName, 'resources/objects/talk.png'); this.load.on(FILE_LOAD_ERROR, (file: {src: string}) => { - this.scene.start(FourOFourSceneName, { - file: file.src + this.scene.start(ErrorSceneName, { + title: 'Network error', + subTitle: 'An error occurred while loading resource:', + message: file.src }); }); this.load.on('filecomplete-tilemapJSON-'+this.MapUrlFile, (key: string, type: string, data: unknown) => { @@ -375,7 +377,7 @@ export class GameScene extends ResizableScene implements CenterListener { //notify game manager can to create currentUser in map this.createCurrentPlayer(); this.removeAllRemotePlayers(); //cleanup the list of remote players in case the scene was rebooted - + this.initCamera(); this.initCirclesCanvas(); @@ -1039,7 +1041,7 @@ export class GameScene extends ResizableScene implements CenterListener { event: addPlayerData }); } - + private doAddPlayer(addPlayerData : AddPlayerInterface): void { //check if exist player, if exist, move position if(this.MapPlayersByKey.has(addPlayerData.userId)){ @@ -1192,7 +1194,7 @@ export class GameScene extends ResizableScene implements CenterListener { // Let's put this in Game coordinates by applying the zoom level: xCenter /= ZOOM_LEVEL * RESOLUTION; yCenter /= ZOOM_LEVEL * RESOLUTION; - + this.cameras.main.startFollow(this.CurrentPlayer, true, 1, 1, xCenter - this.game.renderer.width / 2, yCenter - this.game.renderer.height / 2); } diff --git a/front/src/Phaser/Login/EntryScene.ts b/front/src/Phaser/Login/EntryScene.ts index c7527349..fc551375 100644 --- a/front/src/Phaser/Login/EntryScene.ts +++ b/front/src/Phaser/Login/EntryScene.ts @@ -1,7 +1,7 @@ import {gameManager} from "../Game/GameManager"; import {Scene} from "phaser"; -import {LoginSceneName} from "./LoginScene"; -import {FourOFourSceneName} from "../Reconnecting/FourOFourScene"; +import {handleAxiosError} from "../../Network/axios"; +import {ErrorScene} from "../Reconnecting/ErrorScene"; export const EntrySceneName = "EntryScene"; @@ -20,10 +20,7 @@ export class EntryScene extends Scene { gameManager.init(this.scene).then((nextSceneName) => { this.scene.start(nextSceneName); }).catch((err) => { - console.error(err) - this.scene.start(FourOFourSceneName, { - url: window.location.pathname.toString() - }); + ErrorScene.showError(err, this.scene); }); } } diff --git a/front/src/Phaser/Reconnecting/ErrorScene.ts b/front/src/Phaser/Reconnecting/ErrorScene.ts new file mode 100644 index 00000000..8253c5e8 --- /dev/null +++ b/front/src/Phaser/Reconnecting/ErrorScene.ts @@ -0,0 +1,98 @@ +import {TextField} from "../Components/TextField"; +import Image = Phaser.GameObjects.Image; +import Sprite = Phaser.GameObjects.Sprite; +import Text = Phaser.GameObjects.Text; +import ScenePlugin = Phaser.Scenes.ScenePlugin; + +export const ErrorSceneName = "ErrorScene"; +enum Textures { + icon = "icon", + mainFont = "main_font" +} + +export class ErrorScene extends Phaser.Scene { + private titleField!: TextField; + private subTitleField!: TextField; + private messageField!: Text; + private logo!: Image; + private cat!: Sprite; + private title!: string; + private subTitle!: string; + private message!: string; + + constructor() { + super({ + key: ErrorSceneName + }); + } + + init({ title, subTitle, message }: { title?: string, subTitle?: string, message?: string }) { + this.title = title ? title : ''; + this.subTitle = subTitle ? subTitle : ''; + this.message = message ? message : ''; + } + + preload() { + this.load.image(Textures.icon, "resources/logos/tcm_full.png"); + // Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap + this.load.bitmapFont(Textures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml'); + this.load.spritesheet( + 'cat', + 'resources/characters/pipoya/Cat 01-1.png', + {frameWidth: 32, frameHeight: 32} + ); + } + + create() { + this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, Textures.icon); + this.add.existing(this.logo); + + this.titleField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height / 2, this.title); + + this.subTitleField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height / 2 + 24, this.subTitle); + + this.messageField = this.add.text(this.game.renderer.width / 2, this.game.renderer.height / 2 + 38, this.message, { fontFamily: 'Georgia, "Goudy Bookletter 1911", Times, serif', fontSize: '10px' }); + this.messageField.setOrigin(0.5, 0.5); + + this.cat = this.physics.add.sprite(this.game.renderer.width / 2, this.game.renderer.height / 2 - 32, 'cat', 6); + this.cat.flipY=true; + } + + /** + * Displays the error page, with an error message matching the "error" parameters passed in. + */ + public static showError(error: any, scene: ScenePlugin): void { + console.error(error); + + if (typeof error === 'string' || error instanceof String) { + scene.start(ErrorSceneName, { + title: 'An error occurred', + subTitle: error + }); + } else if (error.response) { + // Axios HTTP error + // client received an error response (5xx, 4xx) + scene.start(ErrorSceneName, { + title: 'HTTP ' + error.response.status + ' - ' + error.response.statusText, + subTitle: 'An error occurred while accessing URL:', + message: error.response.config.url + }); + } else if (error.request) { + // Axios HTTP error + // client never received a response, or request never left + scene.start(ErrorSceneName, { + title: 'Network error', + subTitle: error.message + }); + } else if (error instanceof Error) { + // Error + scene.start(ErrorSceneName, { + title: 'An error occurred', + subTitle: error.name, + message: error.message + }); + } else { + throw error; + } + } +} diff --git a/front/src/Phaser/Reconnecting/FourOFourScene.ts b/front/src/Phaser/Reconnecting/FourOFourScene.ts deleted file mode 100644 index 36106796..00000000 --- a/front/src/Phaser/Reconnecting/FourOFourScene.ts +++ /dev/null @@ -1,68 +0,0 @@ -import {TextField} from "../Components/TextField"; -import Image = Phaser.GameObjects.Image; -import Sprite = Phaser.GameObjects.Sprite; -import Text = Phaser.GameObjects.Text; - -export const FourOFourSceneName = "FourOFourScene"; -enum Textures { - icon = "icon", - mainFont = "main_font" -} - -export class FourOFourScene extends Phaser.Scene { - private mapNotFoundField!: TextField; - private couldNotFindField!: TextField; - private fileNameField!: Text; - private logo!: Image; - private cat!: Sprite; - private file: string|undefined; - private url: string|undefined; - - constructor() { - super({ - key: FourOFourSceneName - }); - } - - init({ file, url }: { file?: string, url?: string }) { - this.file = file; - this.url = url; - } - - preload() { - this.load.image(Textures.icon, "resources/logos/tcm_full.png"); - // Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap - this.load.bitmapFont(Textures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml'); - this.load.spritesheet( - 'cat', - 'resources/characters/pipoya/Cat 01-1.png', - {frameWidth: 32, frameHeight: 32} - ); - } - - create() { - this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, Textures.icon); - this.add.existing(this.logo); - - this.mapNotFoundField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height / 2, "404 - File not found"); - - let text: string = ''; - if (this.file !== undefined) { - text = "Could not load map" - } - if (this.url !== undefined) { - text = "Invalid URL" - } - - this.couldNotFindField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height / 2 + 24, text); - - const url = this.file ? this.file : this.url; - if (url !== undefined) { - this.fileNameField = this.add.text(this.game.renderer.width / 2, this.game.renderer.height / 2 + 38, url, { fontFamily: 'Georgia, "Goudy Bookletter 1911", Times, serif', fontSize: '10px' }); - this.fileNameField.setOrigin(0.5, 0.5); - } - - this.cat = this.physics.add.sprite(this.game.renderer.width / 2, this.game.renderer.height / 2 - 32, 'cat', 6); - this.cat.flipY=true; - } -} diff --git a/front/src/index.ts b/front/src/index.ts index abca6036..acf66cf8 100644 --- a/front/src/index.ts +++ b/front/src/index.ts @@ -6,7 +6,6 @@ import {LoginScene} from "./Phaser/Login/LoginScene"; import {ReconnectingScene} from "./Phaser/Reconnecting/ReconnectingScene"; import {SelectCharacterScene} from "./Phaser/Login/SelectCharacterScene"; import {EnableCameraScene} from "./Phaser/Login/EnableCameraScene"; -import {FourOFourScene} from "./Phaser/Reconnecting/FourOFourScene"; import WebGLRenderer = Phaser.Renderer.WebGL.WebGLRenderer; import {OutlinePipeline} from "./Phaser/Shaders/OutlinePipeline"; import {CustomizeScene} from "./Phaser/Login/CustomizeScene"; @@ -15,6 +14,7 @@ import {EntryScene} from "./Phaser/Login/EntryScene"; import {coWebsiteManager} from "./WebRtc/CoWebsiteManager"; import {MenuScene} from "./Phaser/Menu/MenuScene"; import {localUserStore} from "./Connexion/LocalUserStore"; +import {ErrorScene} from "./Phaser/Reconnecting/ErrorScene"; // Load Jitsi if the environment variable is set. if (JITSI_URL) { @@ -59,7 +59,7 @@ const config: GameConfig = { width: width / RESOLUTION, height: height / RESOLUTION, parent: "game", - scene: [EntryScene, LoginScene, SelectCharacterScene, EnableCameraScene, ReconnectingScene, FourOFourScene, CustomizeScene, MenuScene], + scene: [EntryScene, LoginScene, SelectCharacterScene, EnableCameraScene, ReconnectingScene, ErrorScene, CustomizeScene, MenuScene], zoom: RESOLUTION, fps: fps, dom: {