From 2b820c7d56e82d296ba5df87e44b6a6252cfed01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Fri, 19 Jun 2020 18:18:43 +0200 Subject: [PATCH] Adding an event queue in the GameScene. Events are processed only in the 'update' method. We hope this will solve a number of null pointer errors. See #194 --- front/package.json | 1 + front/src/Phaser/Game/GameScene.ts | 128 ++++++++++++++++++++++++++--- front/yarn.lock | 12 +++ 3 files changed, 131 insertions(+), 10 deletions(-) diff --git a/front/package.json b/front/package.json index dba6ea03..d73eb50d 100644 --- a/front/package.json +++ b/front/package.json @@ -22,6 +22,7 @@ "@types/simple-peer": "^9.6.0", "@types/socket.io-client": "^1.4.32", "phaser": "^3.22.0", + "queue-typescript": "^1.0.1", "simple-peer": "^9.6.2", "socket.io-client": "^2.3.0" }, diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 21e0d0b8..889cab16 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -22,6 +22,8 @@ import {PlayerMovement} from "./PlayerMovement"; import {PlayersPositionInterpolator} from "./PlayersPositionInterpolator"; import {RemotePlayer} from "../Entity/RemotePlayer"; import GameObject = Phaser.GameObjects.GameObject; +import { Queue } from 'queue-typescript'; + export enum Textures { Player = "male1" @@ -32,6 +34,36 @@ export interface GameSceneInitInterface { startLayerName: string|undefined } +interface InitUserPositionEventInterface { + type: 'InitUserPositionEvent' + event: MessageUserPositionInterface[] +} + +interface AddPlayerEventInterface { + type: 'AddPlayerEvent' + event: AddPlayerInterface +} + +interface RemovePlayerEventInterface { + type: 'RemovePlayerEvent' + userId: string +} + +interface UserMovedEventInterface { + type: 'UserMovedEvent' + event: MessageUserMovedInterface +} + +interface GroupCreatedUpdatedEventInterface { + type: 'GroupCreatedUpdatedEvent' + event: GroupCreatedUpdatedMessageInterface +} + +interface DeleteGroupEventInterface { + type: 'DeleteGroupEvent' + groupId: string +} + export class GameScene extends Phaser.Scene { GameManager : GameManager; Terrains : Array; @@ -46,6 +78,7 @@ export class GameScene extends Phaser.Scene { startX: number; startY: number; circleTexture: CanvasTexture; + pendingEvents: Queue = new Queue(); private initPosition: PositionInterface|null = null; private playersPositionInterpolator = new PlayersPositionInterpolator(); @@ -437,13 +470,13 @@ export class GameScene extends Phaser.Scene { EventToClickOnTile(){ // debug code to get a tile properties by clicking on it - this.input.on("pointerdown", (pointer: Phaser.Input.Pointer)=>{ + /*this.input.on("pointerdown", (pointer: Phaser.Input.Pointer)=>{ //pixel position toz tile position 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); } - }); + });*/ } /** @@ -454,6 +487,31 @@ export class GameScene extends Phaser.Scene { this.currentTick = time; this.CurrentPlayer.moveUser(delta); + // Let's handle all events + let event = null; + while (event = this.pendingEvents.dequeue()) { + switch (event.type) { + case "InitUserPositionEvent": + this.doInitUsersPosition(event.event); + break; + case "AddPlayerEvent": + this.doAddPlayer(event.event); + break; + case "RemovePlayerEvent": + this.doRemovePlayer(event.userId); + break; + case "UserMovedEvent": + this.doUpdatePlayerPosition(event.event); + break; + case "GroupCreatedUpdatedEvent": + this.doShareGroupPosition(event.event); + break; + case "DeleteGroupEvent": + this.doDeleteGroup(event.groupId); + break; + } + } + // Let's move all users const updatedPlayersPositions = this.playersPositionInterpolator.getUpdatedPositions(time); updatedPlayersPositions.forEach((moveEvent: HasMovedEvent, userId: string) => { @@ -488,12 +546,21 @@ export class GameScene extends Phaser.Scene { } } + /** + * Called by the connexion when the full list of user position is received. + */ public initUsersPosition(usersPosition: MessageUserPositionInterface[]): void { - if(!this.CurrentPlayer){ - console.error('Cannot initiate users list because map is not loaded yet') - return; - } + this.pendingEvents.enqueue({ + type: "InitUserPositionEvent", + event: usersPosition + }); + } + + /** + * Put all the players on the map on map load. + */ + private doInitUsersPosition(usersPosition: MessageUserPositionInterface[]): void { const currentPlayerId = this.GameManager.getPlayerId(); // clean map @@ -512,10 +579,20 @@ export class GameScene extends Phaser.Scene { }); } + /** + * Called by the connexion when a new player arrives on a map + */ + public addPlayer(addPlayerData : AddPlayerInterface) : void { + this.pendingEvents.enqueue({ + type: "AddPlayerEvent", + event: addPlayerData + }); + } + /** * Create new player */ - public addPlayer(addPlayerData : AddPlayerInterface) : void{ + private doAddPlayer(addPlayerData : AddPlayerInterface) : void { //check if exist player, if exist, move position if(this.MapPlayersByKey.has(addPlayerData.userId)){ this.updatePlayerPosition({ @@ -545,8 +622,18 @@ export class GameScene extends Phaser.Scene { });*/ } + /** + * Called by the connexion when a player is removed from the map + */ public removePlayer(userId: string) { - console.log('Removing player ', userId) + this.pendingEvents.enqueue({ + type: "RemovePlayerEvent", + userId + }); + } + + private doRemovePlayer(userId: string) { + //console.log('Removing player ', userId) const player = this.MapPlayersByKey.get(userId); if (player === undefined) { console.error('Cannot find user with id ', userId); @@ -558,7 +645,14 @@ export class GameScene extends Phaser.Scene { this.playersPositionInterpolator.removePlayer(userId); } - updatePlayerPosition(message: MessageUserMovedInterface): void { + public updatePlayerPosition(message: MessageUserMovedInterface): void { + this.pendingEvents.enqueue({ + type: "UserMovedEvent", + event: message + }); + } + + private doUpdatePlayerPosition(message: MessageUserMovedInterface): void { const player : RemotePlayer | undefined = this.MapPlayersByKey.get(message.userId); if (player === undefined) { throw new Error('Cannot find player with ID "' + message.userId +'"'); @@ -570,7 +664,14 @@ export class GameScene extends Phaser.Scene { this.playersPositionInterpolator.updatePlayerPosition(player.userId, playerMovement); } - shareGroupPosition(groupPositionMessage: GroupCreatedUpdatedMessageInterface) { + public shareGroupPosition(groupPositionMessage: GroupCreatedUpdatedMessageInterface) { + this.pendingEvents.enqueue({ + type: "GroupCreatedUpdatedEvent", + event: groupPositionMessage + }); + } + + private doShareGroupPosition(groupPositionMessage: GroupCreatedUpdatedMessageInterface) { const groupId = groupPositionMessage.groupId; const group = this.groups.get(groupId); @@ -590,6 +691,13 @@ export class GameScene extends Phaser.Scene { } deleteGroup(groupId: string): void { + this.pendingEvents.enqueue({ + type: "DeleteGroupEvent", + groupId + }); + } + + doDeleteGroup(groupId: string): void { const group = this.groups.get(groupId); if(!group){ return; diff --git a/front/yarn.lock b/front/yarn.lock index 7ed8c19a..126536e0 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -2602,6 +2602,11 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +linked-list-typescript@^1.0.11: + version "1.0.15" + resolved "https://registry.yarnpkg.com/linked-list-typescript/-/linked-list-typescript-1.0.15.tgz#faeed93cf9203f102e2158c29edcddda320abe82" + integrity sha512-RIyUu9lnJIyIaMe63O7/aFv/T2v3KsMFuXMBbUQCHX+cgtGro86ETDj5ed0a8gQL2+DFjzYYsgVG4I36/cUwgw== + loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" @@ -3400,6 +3405,13 @@ queue-microtask@^1.1.0: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.1.2.tgz#139bf8186db0c545017ec66c2664ac646d5c571e" integrity sha512-F9wwNePtXrzZenAB3ax0Y8TSKGvuB7Qw16J30hspEUTbfUM+H827XyN3rlpwhVmtm5wuZtbKIHjOnwDn7MUxWQ== +queue-typescript@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/queue-typescript/-/queue-typescript-1.0.1.tgz#2d7842fc3b3e0e3f33d077887a8f2a5bb0baf460" + integrity sha512-tkK08uPfmpPl0cX1WRSU3EoNb/T5zSoZPGkkpfGX4E8QayWvEmLS2cI3pFngNPkNTCU5pCDQ1IwlzN0L5gdFPg== + dependencies: + linked-list-typescript "^1.0.11" + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.3, randombytes@^2.0.5: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"