From 54f2518b5e0d4909092260932afd9f4fbc7a7376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Tue, 9 Jun 2020 23:12:54 +0200 Subject: [PATCH 1/4] Enabling stricter lint on front --- front/.eslintrc.json | 11 +++++++---- front/src/Phaser/Game/GameScene.ts | 3 ++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/front/.eslintrc.json b/front/.eslintrc.json index 0cee14a3..3aab37d9 100644 --- a/front/.eslintrc.json +++ b/front/.eslintrc.json @@ -7,7 +7,8 @@ }, "extends": [ "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended" + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking" ], "globals": { "Atomics": "readonly", @@ -16,12 +17,14 @@ "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 2018, - "sourceType": "module" + "sourceType": "module", + "project": "./tsconfig.json" }, "plugins": [ "@typescript-eslint" ], "rules": { - "no-unused-vars": "off" + "no-unused-vars": "off", + "@typescript-eslint/no-explicit-any": "error" } -} \ No newline at end of file +} diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 2b60fd62..1c979259 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -16,6 +16,7 @@ import {PlayerAnimationNames} from "../Player/Animation"; import {PlayerMovement} from "./PlayerMovement"; import {PlayersPositionInterpolator} from "./PlayersPositionInterpolator"; import {RemotePlayer} from "../Entity/RemotePlayer"; +import GameObject = Phaser.GameObjects.GameObject; export enum Textures { Player = "male1" @@ -347,7 +348,7 @@ export class GameScene extends Phaser.Scene { createCollisionWithPlayer() { //add collision layer this.Layers.forEach((Layer: Phaser.Tilemaps.StaticTilemapLayer) => { - this.physics.add.collider(this.CurrentPlayer, Layer, (object1: any, object2: any) => { + this.physics.add.collider(this.CurrentPlayer, Layer, (object1: GameObject, object2: GameObject) => { //this.CurrentPlayer.say("Collision with layer : "+ (object2 as Tile).layer.name) }); Layer.setCollisionByProperty({collides: true}); From 8348d13bfe788e848ceace63acfc2e7ba9850906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Tue, 9 Jun 2020 23:13:26 +0200 Subject: [PATCH 2/4] Fixing use const instead of let --- front/src/Connection.ts | 2 +- front/src/Logger/MessageUI.ts | 6 +- front/src/Phaser/Components/TextInput.ts | 4 +- front/src/Phaser/Entity/SpeechBubble.ts | 30 ++++---- front/src/Phaser/Game/GameManager.ts | 8 +- front/src/Phaser/Game/GameScene.ts | 74 +++++++++---------- front/src/Phaser/Game/PlayerMovement.ts | 4 +- .../Game/PlayersPositionInterpolator.ts | 2 +- front/src/Phaser/Login/LoginScene.ts | 2 +- .../src/Phaser/Login/SelectCharacterScene.ts | 38 +++++----- front/src/Phaser/Player/Player.ts | 6 +- .../Phaser/Reconnecting/ReconnectingScene.ts | 2 +- .../src/Phaser/UserInput/UserInputManager.ts | 2 +- front/src/WebRtc/MediaManager.ts | 28 +++---- front/src/WebRtc/SimplePeer.ts | 16 ++-- front/src/index.ts | 2 +- front/tests/Phaser/Game/PlayerMovementTest.ts | 6 +- 17 files changed, 116 insertions(+), 116 deletions(-) diff --git a/front/src/Connection.ts b/front/src/Connection.ts index baa9c8a4..45d39841 100644 --- a/front/src/Connection.ts +++ b/front/src/Connection.ts @@ -248,7 +248,7 @@ export class Connection implements ConnectionInterface { if(!this.socket){ return; } - let point = new Point(x, y, direction, moving); + const point = new Point(x, y, direction, moving); this.lastPositionShared = point; this.getSocket().emit(EventMessage.USER_POSITION, point); } diff --git a/front/src/Logger/MessageUI.ts b/front/src/Logger/MessageUI.ts index 6011fb73..2a581091 100644 --- a/front/src/Logger/MessageUI.ts +++ b/front/src/Logger/MessageUI.ts @@ -2,7 +2,7 @@ export class MessageUI { static warningMessage(text: string){ this.removeMessage(); - let body = document.getElementById("body"); + const body = document.getElementById("body"); body?.insertAdjacentHTML('afterbegin', `
${text} @@ -12,13 +12,13 @@ export class MessageUI { static removeMessage(id : string|null = null) { if(!id){ - let messages = document.getElementsByClassName("message-info"); + const messages = document.getElementsByClassName("message-info"); for (let i = 0; i < messages.length; i++){ messages.item(i)?.remove(); } return; } - let previousElement = document.getElementById(id); + const previousElement = document.getElementById(id); if (!previousElement) { return; } diff --git a/front/src/Phaser/Components/TextInput.ts b/front/src/Phaser/Components/TextInput.ts index 92ddcb56..e1de42e9 100644 --- a/front/src/Phaser/Components/TextInput.ts +++ b/front/src/Phaser/Components/TextInput.ts @@ -10,8 +10,8 @@ export class TextInput extends Phaser.GameObjects.BitmapText { this.underLine = this.scene.add.text(x, y+1, '_______', { fontFamily: 'Arial', fontSize: "32px", color: '#ffffff'}) - let keySpace = this.scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE); - let keyBackspace = this.scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.BACKSPACE); + const keySpace = this.scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE); + const keyBackspace = this.scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.BACKSPACE); this.scene.input.keyboard.on('keydown', (event: any) => { if (event.keyCode === 8 && this.text.length > 0) { this.deleteLetter(); diff --git a/front/src/Phaser/Entity/SpeechBubble.ts b/front/src/Phaser/Entity/SpeechBubble.ts index f2385290..30518890 100644 --- a/front/src/Phaser/Entity/SpeechBubble.ts +++ b/front/src/Phaser/Entity/SpeechBubble.ts @@ -13,10 +13,10 @@ export class SpeechBubble { */ constructor(scene: Scene, player: Character, text: string = "") { - let bubbleHeight = 50; - let bubblePadding = 10; - let bubbleWidth = bubblePadding * 2 + text.length * 10; - let arrowHeight = bubbleHeight / 4; + const bubbleHeight = 50; + const bubblePadding = 10; + const bubbleWidth = bubblePadding * 2 + text.length * 10; + const arrowHeight = bubbleHeight / 4; this.bubble = scene.add.graphics({ x: player.x + 16, y: player.y - 80 }); @@ -35,12 +35,12 @@ export class SpeechBubble { this.bubble.fillRoundedRect(0, 0, bubbleWidth, bubbleHeight, 16); // Calculate arrow coordinates - let point1X = Math.floor(bubbleWidth / 7); - let point1Y = bubbleHeight; - let point2X = Math.floor((bubbleWidth / 7) * 2); - let point2Y = bubbleHeight; - let point3X = Math.floor(bubbleWidth / 7); - let point3Y = Math.floor(bubbleHeight + arrowHeight); + const point1X = Math.floor(bubbleWidth / 7); + const point1Y = bubbleHeight; + const point2X = Math.floor((bubbleWidth / 7) * 2); + const point2Y = bubbleHeight; + const point3X = Math.floor(bubbleWidth / 7); + const point3Y = Math.floor(bubbleHeight + arrowHeight); // bubble arrow shadow this.bubble.lineStyle(4, 0x222222, 0.5); @@ -54,7 +54,7 @@ export class SpeechBubble { this.content = scene.add.text(0, 0, text, { fontFamily: 'Arial', fontSize: 20, color: '#000000', align: 'center', wordWrap: { width: bubbleWidth - (bubblePadding * 2) } }); - let bounds = this.content.getBounds(); + const bounds = this.content.getBounds(); this.content.setPosition(this.bubble.x + (bubbleWidth / 2) - (bounds.width / 2), this.bubble.y + (bubbleHeight / 2) - (bounds.height / 2)); } @@ -68,10 +68,10 @@ export class SpeechBubble { this.bubble.setPosition((x + 16), (y - 80)); } if (this.content) { - let bubbleHeight = 50; - let bubblePadding = 10; - let bubbleWidth = bubblePadding * 2 + this.content.text.length * 10; - let bounds = this.content.getBounds(); + const bubbleHeight = 50; + const bubblePadding = 10; + const bubbleWidth = bubblePadding * 2 + this.content.text.length * 10; + const bounds = this.content.getBounds(); //this.content.setPosition(x, y); this.content.setPosition(this.bubble.x + (bubbleWidth / 2) - (bounds.width / 2), this.bubble.y + (bubbleHeight / 2) - (bounds.height / 2)); } diff --git a/front/src/Phaser/Game/GameManager.ts b/front/src/Phaser/Game/GameManager.ts index 7ed0137f..e4f77d8a 100644 --- a/front/src/Phaser/Game/GameManager.ts +++ b/front/src/Phaser/Game/GameManager.ts @@ -83,7 +83,7 @@ export class GameManager { } onUserJoins(message: MessageUserJoined): void { - let userMessage: AddPlayerInterface = { + const userMessage: AddPlayerInterface = { userId: message.userId, character: message.character, name: message.name, @@ -154,11 +154,11 @@ export class GameManager { } loadMap(mapUrl: string, scene: Phaser.Scenes.ScenePlugin, instance: string): string { - let sceneKey = GameScene.getMapKeyByUrl(mapUrl); + const sceneKey = GameScene.getMapKeyByUrl(mapUrl); - let gameIndex = scene.getIndex(sceneKey); + const gameIndex = scene.getIndex(sceneKey); if(gameIndex === -1){ - let game : Phaser.Scene = GameScene.createFromUrl(mapUrl, instance); + const game : Phaser.Scene = GameScene.createFromUrl(mapUrl, instance); scene.add(sceneKey, game, false); } return sceneKey; diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 1c979259..ed5d8956 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -62,7 +62,7 @@ export class GameScene extends Phaser.Scene { private startLayerName: string|undefined; static createFromUrl(mapUrlFile: string, instance: string): GameScene { - let key = GameScene.getMapKeyByUrl(mapUrlFile); + const key = GameScene.getMapKeyByUrl(mapUrlFile); return new GameScene(key, mapUrlFile, instance); } @@ -92,7 +92,7 @@ export class GameScene extends Phaser.Scene { // If the map has already been loaded as part of another GameScene, the "on load" event will not be triggered. // In this case, we check in the cache to see if the map is here and trigger the event manually. if (this.cache.tilemap.exists(this.MapKey)) { - let data = this.cache.tilemap.get(this.MapKey); + const data = this.cache.tilemap.get(this.MapKey); this.onMapLoad(data); } @@ -112,7 +112,7 @@ export class GameScene extends Phaser.Scene { // Triggered when the map is loaded // Load tiles attached to the map recursively this.mapFile = data.data; - let url = this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf('/')); + const url = this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf('/')); this.mapFile.tilesets.forEach((tileset) => { if (typeof tileset.name === 'undefined' || typeof tileset.image === 'undefined') { console.warn("Don't know how to handle tileset ", tileset) @@ -146,7 +146,7 @@ export class GameScene extends Phaser.Scene { //add layer on map this.Layers = new Array(); let depth = -2; - for (let layer of this.mapFile.layers) { + for (const layer of this.mapFile.layers) { if (layer.type === 'tilelayer') { this.addLayer(this.Map.createStaticLayer(layer.name, this.Terrains, 0, 0).setDepth(depth)); } @@ -168,9 +168,9 @@ export class GameScene extends Phaser.Scene { } else { // Now, let's find the start layer if (this.startLayerName) { - for (let layer of this.mapFile.layers) { + for (const layer of this.mapFile.layers) { if (this.startLayerName === layer.name && layer.type === 'tilelayer' && this.isStartLayer(layer)) { - let startPosition = this.startUser(layer); + const startPosition = this.startUser(layer); this.startX = startPosition.x; this.startY = startPosition.y; } @@ -178,9 +178,9 @@ export class GameScene extends Phaser.Scene { } if (this.startX === undefined) { // If we have no start layer specified or if the hash passed does not exist, let's go with the default start position. - for (let layer of this.mapFile.layers) { + for (const layer of this.mapFile.layers) { if (layer.type === 'tilelayer' && layer.name === "start") { - let startPosition = this.startUser(layer); + const startPosition = this.startUser(layer); this.startX = startPosition.x; this.startY = startPosition.y; } @@ -212,12 +212,12 @@ export class GameScene extends Phaser.Scene { // Let's generate the circle for the group delimiter - let circleElement = Object.values(this.textures.list).find((object: Texture) => object.key === 'circleSprite'); + const circleElement = Object.values(this.textures.list).find((object: Texture) => object.key === 'circleSprite'); if(circleElement) { this.textures.remove('circleSprite'); } this.circleTexture = this.textures.createCanvas('circleSprite', 96, 96); - let context = this.circleTexture.context; + const context = this.circleTexture.context; context.beginPath(); context.arc(48, 48, 48, 0, 2 * Math.PI, false); // context.lineWidth = 5; @@ -226,7 +226,7 @@ export class GameScene extends Phaser.Scene { this.circleTexture.refresh(); // Let's alter browser history - let url = new URL(this.MapUrlFile); + const url = new URL(this.MapUrlFile); let path = '/_/'+this.instance+'/'+url.host+url.pathname; if (this.startLayerName) { path += '#'+this.startLayerName; @@ -247,11 +247,11 @@ export class GameScene extends Phaser.Scene { } private getProperty(layer: ITiledMapLayer, name: string): string|boolean|number|undefined { - let properties : any = layer.properties; + const properties : any = layer.properties; if (!properties) { return undefined; } - let obj = properties.find((property:any) => property.name === name); + const obj = properties.find((property:any) => property.name === name); if (obj === undefined) { return undefined; } @@ -266,7 +266,7 @@ export class GameScene extends Phaser.Scene { * @param tileHeight */ private loadNextGame(layer: ITiledMapLayer, mapWidth: number, tileWidth: number, tileHeight: number){ - let exitSceneUrl = this.getExitSceneUrl(layer); + const exitSceneUrl = this.getExitSceneUrl(layer); if (exitSceneUrl === undefined) { throw new Error('Layer is not an exit scene layer.'); } @@ -276,18 +276,18 @@ export class GameScene extends Phaser.Scene { } // TODO: eventually compute a relative URL - let absoluteExitSceneUrl = new URL(exitSceneUrl, this.MapUrlFile).href; - let exitSceneKey = gameManager.loadMap(absoluteExitSceneUrl, this.scene, instance); + const absoluteExitSceneUrl = new URL(exitSceneUrl, this.MapUrlFile).href; + const exitSceneKey = gameManager.loadMap(absoluteExitSceneUrl, this.scene, instance); - let tiles : number[] = layer.data as number[]; + const tiles : number[] = layer.data as number[]; for (let key=0; key < tiles.length; key++) { - let objectKey = tiles[key]; + const objectKey = tiles[key]; if(objectKey === 0){ continue; } //key + 1 because the start x = 0; - let y : number = parseInt(((key + 1) / mapWidth).toString()); - let x : number = key - (y * mapWidth); + const y : number = parseInt(((key + 1) / mapWidth).toString()); + const x : number = key - (y * mapWidth); let hash = new URL(exitSceneUrl, this.MapUrlFile).hash; if (hash) { @@ -317,8 +317,8 @@ export class GameScene extends Phaser.Scene { if(objectKey === 0){ return; } - let y = Math.floor(key / layer.width); - let x = key % layer.width; + const y = Math.floor(key / layer.width); + const x = key % layer.width; possibleStartPositions.push({x: x*32, y: y*32}); }); @@ -431,7 +431,7 @@ export class GameScene extends Phaser.Scene { // debug code to get a tile properties by clicking on it this.input.on("pointerdown", (pointer: Phaser.Input.Pointer)=>{ //pixel position toz tile position - let tile = this.Map.getTileAt(this.Map.worldToTileX(pointer.worldX), this.Map.worldToTileY(pointer.worldY)); + const tile = this.Map.getTileAt(this.Map.worldToTileX(pointer.worldX), this.Map.worldToTileY(pointer.worldY)); if(tile){ this.CurrentPlayer.say("Your touch " + tile.layer.name); } @@ -447,16 +447,16 @@ export class GameScene extends Phaser.Scene { this.CurrentPlayer.moveUser(delta); // Let's move all users - let updatedPlayersPositions = this.playersPositionInterpolator.getUpdatedPositions(time); + const updatedPlayersPositions = this.playersPositionInterpolator.getUpdatedPositions(time); updatedPlayersPositions.forEach((moveEvent: HasMovedEvent, userId: string) => { - let player : RemotePlayer | undefined = this.MapPlayersByKey.get(userId); + const player : RemotePlayer | undefined = this.MapPlayersByKey.get(userId); if (player === undefined) { throw new Error('Cannot find player with ID "' + userId +'"'); } player.updatePosition(moveEvent); }); - let nextSceneKey = this.checkToExit(); + const nextSceneKey = this.checkToExit(); if(nextSceneKey){ // We are completely destroying the current scene to avoid using a half-backed instance when coming back to the same map. this.scene.remove(this.scene.key); @@ -485,7 +485,7 @@ export class GameScene extends Phaser.Scene { return; } - let currentPlayerId = this.GameManager.getPlayerId(); + const currentPlayerId = this.GameManager.getPlayerId(); // clean map this.MapPlayersByKey.forEach((player: RemotePlayer) => { @@ -516,7 +516,7 @@ export class GameScene extends Phaser.Scene { return; } //initialise player - let player = new RemotePlayer( + const player = new RemotePlayer( addPlayerData.userId, this, addPlayerData.position.x, @@ -538,7 +538,7 @@ export class GameScene extends Phaser.Scene { public removePlayer(userId: string) { console.log('Removing player ', userId) - let player = this.MapPlayersByKey.get(userId); + const player = this.MapPlayersByKey.get(userId); if (player === undefined) { console.error('Cannot find user with id ', userId); } else { @@ -550,26 +550,26 @@ export class GameScene extends Phaser.Scene { } updatePlayerPosition(message: MessageUserMovedInterface): void { - let player : RemotePlayer | undefined = this.MapPlayersByKey.get(message.userId); + const player : RemotePlayer | undefined = this.MapPlayersByKey.get(message.userId); if (player === undefined) { throw new Error('Cannot find player with ID "' + message.userId +'"'); } // We do not update the player position directly (because it is sent only every 200ms). // Instead we use the PlayersPositionInterpolator that will do a smooth animation over the next 200ms. - let playerMovement = new PlayerMovement({ x: player.x, y: player.y }, this.currentTick, message.position, this.currentTick + POSITION_DELAY); + const playerMovement = new PlayerMovement({ x: player.x, y: player.y }, this.currentTick, message.position, this.currentTick + POSITION_DELAY); this.playersPositionInterpolator.updatePlayerPosition(player.userId, playerMovement); } shareGroupPosition(groupPositionMessage: GroupCreatedUpdatedMessageInterface) { - let groupId = groupPositionMessage.groupId; + const groupId = groupPositionMessage.groupId; - let group = this.groups.get(groupId); + const group = this.groups.get(groupId); if (group !== undefined) { group.setPosition(Math.round(groupPositionMessage.position.x), Math.round(groupPositionMessage.position.y)); } else { // TODO: circle radius should not be hard stored - let sprite = new Sprite( + const sprite = new Sprite( this, Math.round(groupPositionMessage.position.x), Math.round(groupPositionMessage.position.y), @@ -581,7 +581,7 @@ export class GameScene extends Phaser.Scene { } deleteGroup(groupId: string): void { - let group = this.groups.get(groupId); + const group = this.groups.get(groupId); if(!group){ return; } @@ -591,8 +591,8 @@ export class GameScene extends Phaser.Scene { public static getMapKeyByUrl(mapUrlStart: string) : string { // FIXME: the key should be computed from the full URL of the map. - let startPos = mapUrlStart.indexOf('://')+3; - let endPos = mapUrlStart.indexOf(".json"); + const startPos = mapUrlStart.indexOf('://')+3; + const endPos = mapUrlStart.indexOf(".json"); return mapUrlStart.substring(startPos, endPos); } } diff --git a/front/src/Phaser/Game/PlayerMovement.ts b/front/src/Phaser/Game/PlayerMovement.ts index 1ed2b745..1458335d 100644 --- a/front/src/Phaser/Game/PlayerMovement.ts +++ b/front/src/Phaser/Game/PlayerMovement.ts @@ -23,8 +23,8 @@ export class PlayerMovement { return this.endPosition; } - let x = (this.endPosition.x - this.startPosition.x) * ((tick - this.startTick) / (this.endTick - this.startTick)) + this.startPosition.x; - let y = (this.endPosition.y - this.startPosition.y) * ((tick - this.startTick) / (this.endTick - this.startTick)) + this.startPosition.y; + const x = (this.endPosition.x - this.startPosition.x) * ((tick - this.startTick) / (this.endTick - this.startTick)) + this.startPosition.x; + const y = (this.endPosition.y - this.startPosition.y) * ((tick - this.startTick) / (this.endTick - this.startTick)) + this.startPosition.y; return { x, diff --git a/front/src/Phaser/Game/PlayersPositionInterpolator.ts b/front/src/Phaser/Game/PlayersPositionInterpolator.ts index 19e0f7bc..080c8a17 100644 --- a/front/src/Phaser/Game/PlayersPositionInterpolator.ts +++ b/front/src/Phaser/Game/PlayersPositionInterpolator.ts @@ -17,7 +17,7 @@ export class PlayersPositionInterpolator { } getUpdatedPositions(tick: number) : Map { - let positions = new Map(); + const positions = new Map(); this.playerMovements.forEach((playerMovement: PlayerMovement, userId: string) => { if (playerMovement.isOutdated(tick)) { //console.log("outdated") diff --git a/front/src/Phaser/Login/LoginScene.ts b/front/src/Phaser/Login/LoginScene.ts index 1b7ef76f..e82ece8e 100644 --- a/front/src/Phaser/Login/LoginScene.ts +++ b/front/src/Phaser/Login/LoginScene.ts @@ -67,7 +67,7 @@ export class LoginScene extends Phaser.Scene { this.logo = new Image(this, this.game.renderer.width - 30, this.game.renderer.height - 20, LoginTextures.icon); this.add.existing(this.logo); - let infoText = "Commands: \n - Arrows or Z,Q,S,D to move\n - SHIFT to run"; + const infoText = "Commands: \n - Arrows or Z,Q,S,D to move\n - SHIFT to run"; this.infoTextField = new TextField(this, 10, this.game.renderer.height - 35, infoText); this.input.keyboard.on('keyup-ENTER', () => { diff --git a/front/src/Phaser/Login/SelectCharacterScene.ts b/front/src/Phaser/Login/SelectCharacterScene.ts index dab9d61f..0270a9f5 100644 --- a/front/src/Phaser/Login/SelectCharacterScene.ts +++ b/front/src/Phaser/Login/SelectCharacterScene.ts @@ -63,7 +63,7 @@ export class SelectCharacterScene extends Phaser.Scene { this.pressReturnField = new TextField(this, this.game.renderer.width / 2, 230, 'Press enter to start'); this.pressReturnField.setOrigin(0.5).setCenterAlign() - let rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16; + const rectangleXStart = this.game.renderer.width / 2 - (this.nbCharactersPerRow / 2) * 32 + 16; this.selectedRectangle = this.add.rectangle(rectangleXStart, 90, 32, 32).setStrokeStyle(2, 0xFFFFFF); @@ -103,8 +103,8 @@ export class SelectCharacterScene extends Phaser.Scene { this.createCurrentPlayer(); if (window.localStorage) { - let playerNumberStr: string = window.localStorage.getItem('selectedPlayer') ?? '0'; - let playerNumber: number = Number(playerNumberStr); + const playerNumberStr: string = window.localStorage.getItem('selectedPlayer') ?? '0'; + const playerNumber: number = Number(playerNumberStr); this.selectedRectangleXPos = playerNumber % this.nbCharactersPerRow; this.selectedRectangleYPos = Math.floor(playerNumber / this.nbCharactersPerRow); this.updateSelectedPlayer(); @@ -118,10 +118,10 @@ export class SelectCharacterScene extends Phaser.Scene { private async login(name: string) { return gameManager.connect(name, this.selectedPlayer.texture.key).then(() => { // Do we have a start URL in the address bar? If so, let's redirect to this address - let instanceAndMapUrl = this.findMapUrl(); + const instanceAndMapUrl = this.findMapUrl(); if (instanceAndMapUrl !== null) { - let [mapUrl, instance] = instanceAndMapUrl; - let key = gameManager.loadMap(mapUrl, this.scene, instance); + const [mapUrl, instance] = instanceAndMapUrl; + const key = gameManager.loadMap(mapUrl, this.scene, instance); this.scene.start(key, { startLayerName: window.location.hash ? window.location.hash.substr(1) : undefined } as GameSceneInitInterface); @@ -132,7 +132,7 @@ export class SelectCharacterScene extends Phaser.Scene { if (!scene) { return; } - let key = gameManager.loadMap(window.location.protocol + "//" + scene.mapUrlStart, this.scene, scene.startInstance); + const key = gameManager.loadMap(window.location.protocol + "//" + scene.mapUrlStart, this.scene, scene.startInstance); this.scene.start(key); return scene; }).catch((err) => { @@ -150,28 +150,28 @@ export class SelectCharacterScene extends Phaser.Scene { * Returns the map URL and the instance from the current URL */ private findMapUrl(): [string, string]|null { - let path = window.location.pathname; + const path = window.location.pathname; if (!path.startsWith('/_/')) { return null; } - let instanceAndMap = path.substr(3); - let firstSlash = instanceAndMap.indexOf('/'); + const instanceAndMap = path.substr(3); + const firstSlash = instanceAndMap.indexOf('/'); if (firstSlash === -1) { return null; } - let instance = instanceAndMap.substr(0, firstSlash); + const instance = instanceAndMap.substr(0, firstSlash); return [window.location.protocol+'//'+instanceAndMap.substr(firstSlash+1), instance]; } createCurrentPlayer(): void { for (let i = 0; i { if (d. keyInstance.isDown) { eventsMap.set(d.event, true); diff --git a/front/src/WebRtc/MediaManager.ts b/front/src/WebRtc/MediaManager.ts index 359eac67..80be3f47 100644 --- a/front/src/WebRtc/MediaManager.ts +++ b/front/src/WebRtc/MediaManager.ts @@ -55,7 +55,7 @@ export class MediaManager { } activeVisio(){ - let webRtc = this.getElementByIdOrFail('webRtc'); + const webRtc = this.getElementByIdOrFail('webRtc'); webRtc.classList.add('active'); } @@ -138,9 +138,9 @@ export class MediaManager { */ addActiveVideo(userId : string, userName: string = ""){ this.webrtcInAudio.play(); - let elementRemoteVideo = this.getElementByIdOrFail("activeCam"); + const elementRemoteVideo = this.getElementByIdOrFail("activeCam"); userName = userName.toUpperCase(); - let color = this.getColorByString(userName); + const color = this.getColorByString(userName); elementRemoteVideo.insertAdjacentHTML('beforeend', `
@@ -158,7 +158,7 @@ export class MediaManager { * @param userId */ disabledMicrophoneByUserId(userId: string){ - let element = document.getElementById(`microphone-${userId}`); + const element = document.getElementById(`microphone-${userId}`); if(!element){ return; } @@ -170,7 +170,7 @@ export class MediaManager { * @param userId */ enabledMicrophoneByUserId(userId: string){ - let element = document.getElementById(`microphone-${userId}`); + const element = document.getElementById(`microphone-${userId}`); if(!element){ return; } @@ -223,7 +223,7 @@ export class MediaManager { * @param userId */ removeActiveVideo(userId : string){ - let element = document.getElementById(`div-${userId}`); + const element = document.getElementById(`div-${userId}`); if(!element){ return; } @@ -231,7 +231,7 @@ export class MediaManager { } isConnecting(userId : string): void { - let connectingSpinnerDiv = this.getSpinner(userId); + const connectingSpinnerDiv = this.getSpinner(userId); if (connectingSpinnerDiv === null) { return; } @@ -239,7 +239,7 @@ export class MediaManager { } isConnected(userId : string): void { - let connectingSpinnerDiv = this.getSpinner(userId); + const connectingSpinnerDiv = this.getSpinner(userId); if (connectingSpinnerDiv === null) { return; } @@ -247,11 +247,11 @@ export class MediaManager { } isError(userId : string): void { - let element = document.getElementById(`div-${userId}`); + const element = document.getElementById(`div-${userId}`); if(!element){ return; } - let errorDiv = element.getElementsByClassName('rtc-error').item(0) as HTMLDivElement|null; + const errorDiv = element.getElementsByClassName('rtc-error').item(0) as HTMLDivElement|null; if (errorDiv === null) { return; } @@ -259,11 +259,11 @@ export class MediaManager { } private getSpinner(userId : string): HTMLDivElement|null { - let element = document.getElementById(`div-${userId}`); + const element = document.getElementById(`div-${userId}`); if(!element){ return null; } - let connnectingSpinnerDiv = element.getElementsByClassName('connecting-spinner').item(0) as HTMLDivElement|null; + const connnectingSpinnerDiv = element.getElementsByClassName('connecting-spinner').item(0) as HTMLDivElement|null; return connnectingSpinnerDiv; } @@ -280,14 +280,14 @@ export class MediaManager { } let color = '#'; for (let i = 0; i < 3; i++) { - let value = (hash >> (i * 8)) & 255; + const value = (hash >> (i * 8)) & 255; color += ('00' + value.toString(16)).substr(-2); } return color; } private getElementByIdOrFail(id: string): T { - let elem = document.getElementById(id); + const elem = document.getElementById(id); if (elem === null) { throw new Error("Cannot find HTML element with id '"+id+"'"); } diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts index da1ae3db..3f471253 100644 --- a/front/src/WebRtc/SimplePeer.ts +++ b/front/src/WebRtc/SimplePeer.ts @@ -1,7 +1,7 @@ import {ConnectionInterface, WebRtcDisconnectMessageInterface, WebRtcStartMessageInterface} from "../Connection"; import {MediaManager} from "./MediaManager"; import * as SimplePeerNamespace from "simple-peer"; -let Peer: SimplePeerNamespace.SimplePeer = require('simple-peer'); +const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer'); export interface UserSimplePeer{ userId: string; @@ -95,7 +95,7 @@ export class SimplePeer { let name = user.name; if(!name){ - let userSearch = this.Users.find((userSearch: UserSimplePeer) => userSearch.userId === user.userId); + const userSearch = this.Users.find((userSearch: UserSimplePeer) => userSearch.userId === user.userId); if(userSearch) { name = userSearch.name; } @@ -103,7 +103,7 @@ export class SimplePeer { this.MediaManager.removeActiveVideo(user.userId); this.MediaManager.addActiveVideo(user.userId, name); - let peer : SimplePeerNamespace.Instance = new Peer({ + const peer : SimplePeerNamespace.Instance = new Peer({ initiator: user.initiator ? user.initiator : false, reconnectTimer: 10000, config: { @@ -170,7 +170,7 @@ export class SimplePeer { }); peer.on('data', (chunk: Buffer) => { - let data = JSON.parse(chunk.toString('utf8')); + const data = JSON.parse(chunk.toString('utf8')); if(data.type === "stream"){ this.stream(user.userId, data.stream); } @@ -187,7 +187,7 @@ export class SimplePeer { private closeConnection(userId : string) { try { this.MediaManager.removeActiveVideo(userId); - let peer = this.PeerConnectionArray.get(userId); + const peer = this.PeerConnectionArray.get(userId); if (peer === undefined) { console.warn("Tried to close connection for user "+userId+" but could not find user") return; @@ -222,7 +222,7 @@ export class SimplePeer { if(data.signal.type === "offer"){ this.createPeerConnection(data); } - let peer = this.PeerConnectionArray.get(data.userId); + const peer = this.PeerConnectionArray.get(data.userId); if (peer !== undefined) { peer.signal(data.signal); } else { @@ -253,8 +253,8 @@ export class SimplePeer { */ private addMedia (userId : any = null) { try { - let localStream: MediaStream|null = this.MediaManager.localStream; - let peer = this.PeerConnectionArray.get(userId); + const localStream: MediaStream|null = this.MediaManager.localStream; + const peer = this.PeerConnectionArray.get(userId); if(localStream === null) { //send fake signal if(peer === undefined){ diff --git a/front/src/index.ts b/front/src/index.ts index 843925ac..6221d3ad 100644 --- a/front/src/index.ts +++ b/front/src/index.ts @@ -24,7 +24,7 @@ const config: GameConfig = { cypressAsserter.gameStarted(); -let game = new Phaser.Game(config); +const game = new Phaser.Game(config); window.addEventListener('resize', function (event) { game.scale.resize(window.innerWidth / RESOLUTION, window.innerHeight / RESOLUTION); diff --git a/front/tests/Phaser/Game/PlayerMovementTest.ts b/front/tests/Phaser/Game/PlayerMovementTest.ts index e65dbec8..ce2e2767 100644 --- a/front/tests/Phaser/Game/PlayerMovementTest.ts +++ b/front/tests/Phaser/Game/PlayerMovementTest.ts @@ -3,7 +3,7 @@ import {PlayerMovement} from "../../../src/Phaser/Game/PlayerMovement"; describe("Interpolation / Extrapolation", () => { it("should interpolate", () => { - let playerMovement = new PlayerMovement({ + const playerMovement = new PlayerMovement({ x: 100, y: 200 }, 42000, { @@ -39,7 +39,7 @@ describe("Interpolation / Extrapolation", () => { }); it("should not extrapolate if we stop", () => { - let playerMovement = new PlayerMovement({ + const playerMovement = new PlayerMovement({ x: 100, y: 200 }, 42000, { @@ -57,7 +57,7 @@ describe("Interpolation / Extrapolation", () => { }); it("should should keep moving until it stops", () => { - let playerMovement = new PlayerMovement({ + const playerMovement = new PlayerMovement({ x: 100, y: 200 }, 42000, { From 39928b46f9982d5db3e8916d917bb82c6e77e774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Wed, 10 Jun 2020 12:15:25 +0200 Subject: [PATCH 3/4] Removing any in the front --- front/src/Cypress/CypressAsserter.ts | 12 ++++-- front/src/Phaser/Game/GameManager.ts | 6 +-- front/src/Phaser/Game/GameScene.ts | 27 ++++++------- .../src/Phaser/UserInput/UserInputManager.ts | 13 +++--- front/src/WebRtc/MediaManager.ts | 40 +++++++++++-------- 5 files changed, 52 insertions(+), 46 deletions(-) diff --git a/front/src/Cypress/CypressAsserter.ts b/front/src/Cypress/CypressAsserter.ts index 95adb156..82eeab1f 100644 --- a/front/src/Cypress/CypressAsserter.ts +++ b/front/src/Cypress/CypressAsserter.ts @@ -1,13 +1,17 @@ -declare let window:any; +declare let window:WindowWithCypressAsserter; + +interface WindowWithCypressAsserter extends Window { + cypressAsserter: CypressAsserter; +} //this class is used to communicate with cypress, our e2e testing client //Since cypress cannot manipulate canvas, we notified it with console logs class CypressAsserter { - + constructor() { window.cypressAsserter = this } - + gameStarted() { console.log('Started the game') } @@ -29,4 +33,4 @@ class CypressAsserter { } } -export const cypressAsserter = new CypressAsserter() \ No newline at end of file +export const cypressAsserter = new CypressAsserter() diff --git a/front/src/Phaser/Game/GameManager.ts b/front/src/Phaser/Game/GameManager.ts index e4f77d8a..ec20411f 100644 --- a/front/src/Phaser/Game/GameManager.ts +++ b/front/src/Phaser/Game/GameManager.ts @@ -1,6 +1,6 @@ import {GameScene} from "./GameScene"; import { - Connection, + Connection, ConnectionInterface, GroupCreatedUpdatedMessageInterface, ListMessageUserPositionInterface, MessageUserJoined, @@ -44,11 +44,11 @@ export class GameManager { //this.status = StatusGameManagerEnum.IN_PROGRESS; } - connect(name: string, characterUserSelected : string) { + public connect(name: string, characterUserSelected : string): Promise { this.playerName = name; this.characterUserSelected = characterUserSelected; this.ConnectionInstance = new Connection(this); - return this.ConnectionInstance.createConnection(name, characterUserSelected).then((data : any) => { + return this.ConnectionInstance.createConnection(name, characterUserSelected).then((data : ConnectionInterface) => { this.SimplePeer = new SimplePeer(this.ConnectionInstance); return data; }).catch((err) => { diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index ed5d8956..42115915 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -58,7 +58,7 @@ export class GameScene extends Phaser.Scene { y: -1000 } - PositionNextScene: Array = new Array(); + private PositionNextScene: Array> = new Array>(); private startLayerName: string|undefined; static createFromUrl(mapUrlFile: string, instance: string): GameScene { @@ -295,15 +295,13 @@ export class GameScene extends Phaser.Scene { } //push and save switching case - // TODO: this is not efficient. We should refactor that to enable a search by key. For instance: this.PositionNextScene[y][x] = exitSceneKey - this.PositionNextScene.push({ - xStart: (x * tileWidth), - yStart: (y * tileWidth), - xEnd: ((x +1) * tileHeight), - yEnd: ((y + 1) * tileHeight), + if (this.PositionNextScene[y] === undefined) { + this.PositionNextScene[y] = new Array<{key: string, hash: string}>(); + } + this.PositionNextScene[y][x] = { key: exitSceneKey, hash - }) + } } } @@ -469,14 +467,15 @@ export class GameScene extends Phaser.Scene { /** * */ - checkToExit(){ - if(this.PositionNextScene.length === 0){ + checkToExit(): {key: string, hash: string} | null { + const x = Math.floor(this.CurrentPlayer.x / 32); + const y = Math.floor(this.CurrentPlayer.y / 32); + + if (this.PositionNextScene[y] !== undefined && this.PositionNextScene[y][x] !== undefined) { + return this.PositionNextScene[y][x]; + } else { return null; } - return this.PositionNextScene.find((position : any) => { - return position.xStart <= this.CurrentPlayer.x && this.CurrentPlayer.x <= position.xEnd - && position.yStart <= this.CurrentPlayer.y && this.CurrentPlayer.y <= position.yEnd - }) } public initUsersPosition(usersPosition: MessageUserPositionInterface[]): void { diff --git a/front/src/Phaser/UserInput/UserInputManager.ts b/front/src/Phaser/UserInput/UserInputManager.ts index 1b68feff..eddbbf74 100644 --- a/front/src/Phaser/UserInput/UserInputManager.ts +++ b/front/src/Phaser/UserInput/UserInputManager.ts @@ -1,4 +1,3 @@ -import Map = Phaser.Structs.Map; import {GameScene} from "../Game/GameScene"; interface UserInputManagerDatum { @@ -18,15 +17,13 @@ export enum UserInputEvent { //we cannot the map structure so we have to create a replacment export class ActiveEventList { - private KeysCode : any; - constructor() { - this.KeysCode = {}; - } + private KeysCode : Map = new Map(); + get(event: UserInputEvent): boolean { - return this.KeysCode[event] || false; + return this.KeysCode.get(event) || false; } - set(event: UserInputEvent, value: boolean): boolean { - return this.KeysCode[event] = true; + set(event: UserInputEvent, value: boolean): void { + this.KeysCode.set(event, value); } } diff --git a/front/src/WebRtc/MediaManager.ts b/front/src/WebRtc/MediaManager.ts index 80be3f47..b70ea9de 100644 --- a/front/src/WebRtc/MediaManager.ts +++ b/front/src/WebRtc/MediaManager.ts @@ -1,18 +1,18 @@ -const videoConstraint: {width : any, height: any, facingMode : string} = { +const videoConstraint: boolean|MediaTrackConstraints = { width: { ideal: 1280 }, height: { ideal: 720 }, facingMode: "user" }; export class MediaManager { localStream: MediaStream|null = null; - remoteVideo: Array = new Array(); + private remoteVideo: Map = new Map(); myCamVideo: HTMLVideoElement; - cinemaClose: any = null; - cinema: any = null; - microphoneClose: any = null; - microphone: any = null; + cinemaClose: HTMLImageElement; + cinema: HTMLImageElement; + microphoneClose: HTMLImageElement; + microphone: HTMLImageElement; webrtcInAudio: HTMLAudioElement; - constraintsMedia : {audio : any, video : any} = { + constraintsMedia : MediaStreamConstraints = { audio: true, video: videoConstraint }; @@ -25,29 +25,29 @@ export class MediaManager { this.webrtcInAudio = this.getElementByIdOrFail('audio-webrtc-in'); this.webrtcInAudio.volume = 0.2; - this.microphoneClose = document.getElementById('microphone-close'); + this.microphoneClose = this.getElementByIdOrFail('microphone-close'); this.microphoneClose.style.display = "none"; - this.microphoneClose.addEventListener('click', (e: any) => { + this.microphoneClose.addEventListener('click', (e: MouseEvent) => { e.preventDefault(); this.enabledMicrophone(); //update tracking }); - this.microphone = document.getElementById('microphone'); - this.microphone.addEventListener('click', (e: any) => { + this.microphone = this.getElementByIdOrFail('microphone'); + this.microphone.addEventListener('click', (e: MouseEvent) => { e.preventDefault(); this.disabledMicrophone(); //update tracking }); - this.cinemaClose = document.getElementById('cinema-close'); + this.cinemaClose = this.getElementByIdOrFail('cinema-close'); this.cinemaClose.style.display = "none"; - this.cinemaClose.addEventListener('click', (e: any) => { + this.cinemaClose.addEventListener('click', (e: MouseEvent) => { e.preventDefault(); this.enabledCamera(); //update tracking }); - this.cinema = document.getElementById('cinema'); - this.cinema.addEventListener('click', (e: any) => { + this.cinema = this.getElementByIdOrFail('cinema'); + this.cinema.addEventListener('click', (e: MouseEvent) => { e.preventDefault(); this.disabledCamera(); //update tracking @@ -150,7 +150,7 @@ export class MediaManager {
`); - this.remoteVideo[(userId as any)] = document.getElementById(userId); + this.remoteVideo.set(userId, this.getElementByIdOrFail(userId)); } /** @@ -215,7 +215,12 @@ export class MediaManager { * @param stream */ addStreamRemoteVideo(userId : string, stream : MediaStream){ - this.remoteVideo[(userId as any)].srcObject = stream; + const remoteVideo = this.remoteVideo.get(userId); + if (remoteVideo === undefined) { + console.error('Unable to find video for ', userId); + return; + } + remoteVideo.srcObject = stream; } /** @@ -228,6 +233,7 @@ export class MediaManager { return; } element.remove(); + this.remoteVideo.delete(userId); } isConnecting(userId : string): void { From e2be99490bdb4ea59ac77f33c5771ed5d0690a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Fri, 19 Jun 2020 16:36:40 +0200 Subject: [PATCH 4/4] Finishing removing any reference to "any" in the front. --- front/src/Connection.ts | 27 +++++++++++---- front/src/Enum/EnvironmentVariable.ts | 2 +- front/src/Phaser/Components/TextInput.ts | 2 +- front/src/Phaser/Entity/Character.ts | 7 +++- front/src/Phaser/Game/GameScene.ts | 34 ++++++++++++------- front/src/Phaser/Login/LoginScene.ts | 4 +-- .../src/Phaser/Login/SelectCharacterScene.ts | 21 ++++++------ front/src/Phaser/Map/ITiledMap.ts | 14 +++++++- .../Phaser/Reconnecting/ReconnectingScene.ts | 6 ---- front/src/WebRtc/SimplePeer.ts | 19 +++++++---- 10 files changed, 89 insertions(+), 47 deletions(-) diff --git a/front/src/Connection.ts b/front/src/Connection.ts index 45d39841..b6b251f0 100644 --- a/front/src/Connection.ts +++ b/front/src/Connection.ts @@ -8,6 +8,7 @@ const SocketIo = require('socket.io-client'); import Socket = SocketIOClient.Socket; import {PlayerAnimationNames} from "./Phaser/Player/Animation"; import {UserSimplePeer} from "./WebRtc/SimplePeer"; +import {SignalData} from "simple-peer"; enum EventMessage{ @@ -110,22 +111,29 @@ export interface WebRtcDisconnectMessageInterface { userId: string } +export interface WebRtcSignalMessageInterface { + userId: string, + receiverId: string, + roomId: string, + signal: SignalData +} + export interface ConnectionInterface { socket: Socket|null; token: string|null; name: string|null; userId: string|null; - createConnection(name: string, characterSelected: string): Promise; + createConnection(name: string, characterSelected: string): Promise; - loadStartMap(): Promise; + loadStartMap(): Promise; joinARoom(roomId: string, startX: number, startY: number, direction: string, moving: boolean): void; sharePosition(x: number, y: number, direction: string, moving: boolean): void; /*webrtc*/ - sendWebrtcSignal(signal: any, roomId: string, userId?: string|null, receiverId?: string): void; + sendWebrtcSignal(signal: unknown, roomId: string, userId?: string|null, receiverId?: string): void; receiveWebrtcSignal(callBack: Function): void; @@ -134,6 +142,11 @@ export interface ConnectionInterface { disconnectMessage(callBack: (message: WebRtcDisconnectMessageInterface) => void): void; } +export interface StartMapInterface { + mapUrlStart: string, + startInstance: string +} + export class Connection implements ConnectionInterface { socket: Socket|null = null; token: string|null = null; @@ -225,7 +238,7 @@ export class Connection implements ConnectionInterface { } //TODO add middleware with access token to secure api - loadStartMap() : Promise { + loadStartMap() : Promise { return Axios.get(`${API_URL}/start-map`) .then((res) => { return res.data; @@ -236,7 +249,7 @@ export class Connection implements ConnectionInterface { } joinARoom(roomId: string, startX: number, startY: number, direction: string, moving: boolean): void { - let point = new Point(startX, startY, direction, moving); + const point = new Point(startX, startY, direction, moving); this.lastPositionShared = point; this.getSocket().emit(EventMessage.JOIN_ROOM, { roomId, position: {x: startX, y: startY, direction, moving }}, (userPositions: MessageUserPositionInterface[]) => { this.GameManager.initUsersPosition(userPositions); @@ -284,7 +297,7 @@ export class Connection implements ConnectionInterface { }) } - sendWebrtcSignal(signal: any, roomId: string, userId? : string|null, receiverId? : string) { + sendWebrtcSignal(signal: unknown, roomId: string, userId? : string|null, receiverId? : string) { return this.getSocket().emit(EventMessage.WEBRTC_SIGNAL, { userId: userId ? userId : this.userId, receiverId: receiverId ? receiverId : this.userId, @@ -297,7 +310,7 @@ export class Connection implements ConnectionInterface { this.getSocket().on(EventMessage.WEBRTC_START, callback); } - receiveWebrtcSignal(callback: Function) { + receiveWebrtcSignal(callback: (message: WebRtcSignalMessageInterface) => void) { return this.getSocket().on(EventMessage.WEBRTC_SIGNAL, callback); } diff --git a/front/src/Enum/EnvironmentVariable.ts b/front/src/Enum/EnvironmentVariable.ts index 2fbf7979..6e0edd8f 100644 --- a/front/src/Enum/EnvironmentVariable.ts +++ b/front/src/Enum/EnvironmentVariable.ts @@ -1,4 +1,4 @@ -const DEBUG_MODE: boolean = process.env.DEBUG_MODE as any === true; +const DEBUG_MODE: boolean = process.env.DEBUG_MODE == "true"; const API_URL = process.env.API_URL || "http://api.workadventure.localhost"; const RESOLUTION = 3; const ZOOM_LEVEL = 1/*3/4*/; diff --git a/front/src/Phaser/Components/TextInput.ts b/front/src/Phaser/Components/TextInput.ts index e1de42e9..3a20eadf 100644 --- a/front/src/Phaser/Components/TextInput.ts +++ b/front/src/Phaser/Components/TextInput.ts @@ -12,7 +12,7 @@ export class TextInput extends Phaser.GameObjects.BitmapText { const keySpace = this.scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE); const keyBackspace = this.scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.BACKSPACE); - this.scene.input.keyboard.on('keydown', (event: any) => { + this.scene.input.keyboard.on('keydown', (event: KeyboardEvent) => { if (event.keyCode === 8 && this.text.length > 0) { this.deleteLetter(); } else if ((event.keyCode === 32 || (event.keyCode >= 48 && event.keyCode <= 90)) && this.text.length < maxLength) { diff --git a/front/src/Phaser/Entity/Character.ts b/front/src/Phaser/Entity/Character.ts index ba6a8228..7453dc75 100644 --- a/front/src/Phaser/Entity/Character.ts +++ b/front/src/Phaser/Entity/Character.ts @@ -2,7 +2,12 @@ import {PlayerAnimationNames} from "../Player/Animation"; import {SpeechBubble} from "./SpeechBubble"; import BitmapText = Phaser.GameObjects.BitmapText; -export const PLAYER_RESOURCES: Array = [ +export interface PlayerResourceDescriptionInterface { + name: string, + img: string +} + +export const PLAYER_RESOURCES: Array = [ {name: "male1", img: "resources/characters/pipoya/Male 01-1.png" /*, x: 32, y: 32*/}, {name: "male2", img: "resources/characters/pipoya/Male 02-2.png"/*, x: 64, y: 32*/}, {name: "male3", img: "resources/characters/pipoya/Male 03-4.png"/*, x: 96, y: 32*/}, diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 42115915..21e0d0b8 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -6,8 +6,13 @@ import { } from "../../Connection"; import {CurrentGamerInterface, hasMovedEventName, Player} from "../Player/Player"; import { DEBUG_MODE, ZOOM_LEVEL, POSITION_DELAY } from "../../Enum/EnvironmentVariable"; -import {ITiledMap, ITiledMapLayer, ITiledTileSet} from "../Map/ITiledMap"; -import {PLAYER_RESOURCES} from "../Entity/Character"; +import { + ITiledMap, + ITiledMapLayer, + ITiledMapLayerProperty, + ITiledTileSet +} from "../Map/ITiledMap"; +import {PLAYER_RESOURCES, PlayerResourceDescriptionInterface} from "../Entity/Character"; import Texture = Phaser.Textures.Texture; import Sprite = Phaser.GameObjects.Sprite; import CanvasTexture = Phaser.Textures.CanvasTexture; @@ -84,7 +89,7 @@ export class GameScene extends Phaser.Scene { //hook preload scene preload(): void { this.GameManager.setCurrentGameScene(this); - this.load.on('filecomplete-tilemapJSON-'+this.MapKey, (key: string, type: string, data: any) => { + this.load.on('filecomplete-tilemapJSON-'+this.MapKey, (key: string, type: string, data: unknown) => { this.onMapLoad(data); }); //TODO strategy to add access token @@ -97,7 +102,7 @@ export class GameScene extends Phaser.Scene { } //add player png - PLAYER_RESOURCES.forEach((playerResource: any) => { + PLAYER_RESOURCES.forEach((playerResource: PlayerResourceDescriptionInterface) => { this.load.spritesheet( playerResource.name, playerResource.img, @@ -108,6 +113,8 @@ export class GameScene extends Phaser.Scene { this.load.bitmapFont('main_font', 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml'); } + // FIXME: we need to put a "unknown" instead of a "any" and validate the structure of the JSON we are receiving. + // eslint-disable-next-line @typescript-eslint/no-explicit-any private onMapLoad(data: any): void { // Triggered when the map is loaded // Load tiles attached to the map recursively @@ -247,11 +254,11 @@ export class GameScene extends Phaser.Scene { } private getProperty(layer: ITiledMapLayer, name: string): string|boolean|number|undefined { - const properties : any = layer.properties; + const properties = layer.properties; if (!properties) { return undefined; } - const obj = properties.find((property:any) => property.name === name); + const obj = properties.find((property: ITiledMapLayerProperty) => property.name === name); if (obj === undefined) { return undefined; } @@ -309,8 +316,11 @@ export class GameScene extends Phaser.Scene { * @param layer */ private startUser(layer: ITiledMapLayer): PositionInterface { - let tiles : any = layer.data; - let possibleStartPositions : PositionInterface[] = []; + const tiles = layer.data; + if (typeof(tiles) === 'string') { + throw new Error('The content of a JSON map must be filled as a JSON array, not as a string'); + } + const possibleStartPositions : PositionInterface[] = []; tiles.forEach((objectKey : number, key: number) => { if(objectKey === 0){ return; @@ -362,11 +372,11 @@ export class GameScene extends Phaser.Scene { } createCollisionObject(){ - this.Objects.forEach((Object : Phaser.Physics.Arcade.Sprite) => { - this.physics.add.collider(this.CurrentPlayer, Object, (object1: any, object2: any) => { - //this.CurrentPlayer.say("Collision with object : " + (object2 as Phaser.Physics.Arcade.Sprite).texture.key) + /*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(){ diff --git a/front/src/Phaser/Login/LoginScene.ts b/front/src/Phaser/Login/LoginScene.ts index e82ece8e..5177659b 100644 --- a/front/src/Phaser/Login/LoginScene.ts +++ b/front/src/Phaser/Login/LoginScene.ts @@ -4,7 +4,7 @@ import {TextInput} from "../Components/TextInput"; import {ClickButton} from "../Components/ClickButton"; import Image = Phaser.GameObjects.Image; import Rectangle = Phaser.GameObjects.Rectangle; -import {PLAYER_RESOURCES} from "../Entity/Character"; +import {PLAYER_RESOURCES, PlayerResourceDescriptionInterface} from "../Entity/Character"; import {cypressAsserter} from "../../Cypress/CypressAsserter"; import {SelectCharacterSceneInitDataInterface, SelectCharacterSceneName} from "./SelectCharacterScene"; @@ -40,7 +40,7 @@ export class LoginScene extends Phaser.Scene { this.load.bitmapFont(LoginTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml'); cypressAsserter.preloadFinished(); //add player png - PLAYER_RESOURCES.forEach((playerResource: any) => { + PLAYER_RESOURCES.forEach((playerResource: PlayerResourceDescriptionInterface) => { this.load.spritesheet( playerResource.name, playerResource.img, diff --git a/front/src/Phaser/Login/SelectCharacterScene.ts b/front/src/Phaser/Login/SelectCharacterScene.ts index 0270a9f5..316ee897 100644 --- a/front/src/Phaser/Login/SelectCharacterScene.ts +++ b/front/src/Phaser/Login/SelectCharacterScene.ts @@ -3,8 +3,9 @@ import {TextField} from "../Components/TextField"; import {ClickButton} from "../Components/ClickButton"; import Image = Phaser.GameObjects.Image; import Rectangle = Phaser.GameObjects.Rectangle; -import {PLAYER_RESOURCES} from "../Entity/Character"; +import {PLAYER_RESOURCES, PlayerResourceDescriptionInterface} from "../Entity/Character"; import {GameSceneInitInterface} from "../Game/GameScene"; +import {StartMapInterface} from "../../Connection"; //todo: put this constants in a dedicated file export const SelectCharacterSceneName = "SelectCharacterScene"; @@ -47,7 +48,7 @@ export class SelectCharacterScene extends Phaser.Scene { // Note: arcade.png from the Phaser 3 examples at: https://github.com/photonstorm/phaser3-examples/tree/master/public/assets/fonts/bitmap this.load.bitmapFont(LoginTextures.mainFont, 'resources/fonts/arcade.png', 'resources/fonts/arcade.xml'); //add player png - PLAYER_RESOURCES.forEach((playerResource: any) => { + PLAYER_RESOURCES.forEach((playerResource: PlayerResourceDescriptionInterface) => { this.load.spritesheet( playerResource.name, playerResource.img, @@ -115,7 +116,7 @@ export class SelectCharacterScene extends Phaser.Scene { this.pressReturnField.setVisible(!!(Math.floor(time / 500) % 2)); } - private async login(name: string) { + private async login(name: string): Promise { return gameManager.connect(name, this.selectedPlayer.texture.key).then(() => { // Do we have a start URL in the address bar? If so, let's redirect to this address const instanceAndMapUrl = this.findMapUrl(); @@ -125,16 +126,16 @@ export class SelectCharacterScene extends Phaser.Scene { this.scene.start(key, { startLayerName: window.location.hash ? window.location.hash.substr(1) : undefined } as GameSceneInitInterface); - return mapUrl; + return { + mapUrlStart: mapUrl, + startInstance: instance + }; } else { // If we do not have a map address in the URL, let's ask the server for a start map. - return gameManager.loadStartMap().then((scene : any) => { - if (!scene) { - return; - } - const key = gameManager.loadMap(window.location.protocol + "//" + scene.mapUrlStart, this.scene, scene.startInstance); + return gameManager.loadStartMap().then((startMap: StartMapInterface) => { + const key = gameManager.loadMap(window.location.protocol + "//" + startMap.mapUrlStart, this.scene, startMap.startInstance); this.scene.start(key); - return scene; + return startMap; }).catch((err) => { console.error(err); throw err; diff --git a/front/src/Phaser/Map/ITiledMap.ts b/front/src/Phaser/Map/ITiledMap.ts index ca10f218..2a82e93a 100644 --- a/front/src/Phaser/Map/ITiledMap.ts +++ b/front/src/Phaser/Map/ITiledMap.ts @@ -26,12 +26,24 @@ export interface ITiledMap { version: number; } +export interface ITiledMapLayerProperty { + name: string; + type: string; + value: string|boolean|number|undefined; +} + +/*export interface ITiledMapLayerBooleanProperty { + name: string, + type: 'bool', + value: boolean +}*/ + export interface ITiledMapLayer { data: number[]|string; height: number; name: string; opacity: number; - properties: {[key: string]: string}; + properties: ITiledMapLayerProperty[]; encoding: string; compression?: string; diff --git a/front/src/Phaser/Reconnecting/ReconnectingScene.ts b/front/src/Phaser/Reconnecting/ReconnectingScene.ts index 2ee91358..7a377b66 100644 --- a/front/src/Phaser/Reconnecting/ReconnectingScene.ts +++ b/front/src/Phaser/Reconnecting/ReconnectingScene.ts @@ -1,11 +1,5 @@ -import {gameManager} from "../Game/GameManager"; import {TextField} from "../Components/TextField"; -import {TextInput} from "../Components/TextInput"; -import {ClickButton} from "../Components/ClickButton"; import Image = Phaser.GameObjects.Image; -import Rectangle = Phaser.GameObjects.Rectangle; -import {PLAYER_RESOURCES} from "../Entity/Character"; -import {cypressAsserter} from "../../Cypress/CypressAsserter"; import Sprite = Phaser.GameObjects.Sprite; export const ReconnectingSceneName = "ReconnectingScene"; diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts index 3f471253..f5c8e7ef 100644 --- a/front/src/WebRtc/SimplePeer.ts +++ b/front/src/WebRtc/SimplePeer.ts @@ -1,4 +1,9 @@ -import {ConnectionInterface, WebRtcDisconnectMessageInterface, WebRtcStartMessageInterface} from "../Connection"; +import { + ConnectionInterface, + WebRtcDisconnectMessageInterface, + WebRtcSignalMessageInterface, + WebRtcStartMessageInterface +} from "../Connection"; import {MediaManager} from "./MediaManager"; import * as SimplePeerNamespace from "simple-peer"; const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer'); @@ -36,7 +41,7 @@ export class SimplePeer { private initialise() { //receive signal by gemer - this.Connection.receiveWebrtcSignal((message: any) => { + this.Connection.receiveWebrtcSignal((message: WebRtcSignalMessageInterface) => { this.receiveWebrtcSignal(message); }); @@ -122,7 +127,7 @@ export class SimplePeer { this.PeerConnectionArray.set(user.userId, peer); //start listen signal for the peer connection - peer.on('signal', (data: any) => { + peer.on('signal', (data: unknown) => { this.sendWebrtcSignal(data, user.userId); }); @@ -159,6 +164,7 @@ export class SimplePeer { this.closeConnection(user.userId); }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any peer.on('error', (err: any) => { console.error(`error => ${user.userId} => ${err.code}`, err); this.MediaManager.isError(user.userId); @@ -208,7 +214,7 @@ export class SimplePeer { * @param userId * @param data */ - private sendWebrtcSignal(data: any, userId : string) { + private sendWebrtcSignal(data: unknown, userId : string) { try { this.Connection.sendWebrtcSignal(data, this.WebRtcRoomId, null, userId); }catch (e) { @@ -216,7 +222,8 @@ export class SimplePeer { } } - private receiveWebrtcSignal(data: any) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + private receiveWebrtcSignal(data: WebRtcSignalMessageInterface) { try { //if offer type, create peer connection if(data.signal.type === "offer"){ @@ -251,7 +258,7 @@ export class SimplePeer { * * @param userId */ - private addMedia (userId : any = null) { + private addMedia (userId : string) { try { const localStream: MediaStream|null = this.MediaManager.localStream; const peer = this.PeerConnectionArray.get(userId);