From 5a3d510f052e275f2a5e34eb7e79bffef3197bcc Mon Sep 17 00:00:00 2001 From: Alexis Faizeau Date: Tue, 2 Nov 2021 10:51:02 +0100 Subject: [PATCH] Create GameMapProperties index --- front/src/Phaser/Components/TextUtils.ts | 3 +- front/src/Phaser/Game/GameMap.ts | 10 +-- front/src/Phaser/Game/GameMapProperties.ts | 37 +++++++++++ .../Phaser/Game/GameMapPropertiesListener.ts | 27 ++++---- front/src/Phaser/Game/GameScene.ts | 61 +++++++++---------- .../src/Phaser/Game/SharedVariablesManager.ts | 7 ++- .../Phaser/Game/StartPositionCalculator.ts | 3 +- front/src/WebRtc/LayoutManager.ts | 9 --- 8 files changed, 92 insertions(+), 65 deletions(-) create mode 100644 front/src/Phaser/Game/GameMapProperties.ts diff --git a/front/src/Phaser/Components/TextUtils.ts b/front/src/Phaser/Components/TextUtils.ts index e9cb9260..b8f1bd69 100644 --- a/front/src/Phaser/Components/TextUtils.ts +++ b/front/src/Phaser/Components/TextUtils.ts @@ -1,6 +1,7 @@ import type { ITiledMapObject } from "../Map/ITiledMap"; import type { GameScene } from "../Game/GameScene"; import { type } from "os"; +import { GameMapProperties } from "../Game/GameMapProperties"; export class TextUtils { public static createTextFromITiledMapObject(scene: GameScene, object: ITiledMapObject): void { @@ -32,7 +33,7 @@ export class TextUtils { } if (object.properties !== undefined) { for (const property of object.properties) { - if (property.name === "font-family" && typeof property.value === "string") { + if (property.name === GameMapProperties.FONT_FAMILY && typeof property.value === "string") { options.fontFamily = property.value; } } diff --git a/front/src/Phaser/Game/GameMap.ts b/front/src/Phaser/Game/GameMap.ts index cd11c179..17740874 100644 --- a/front/src/Phaser/Game/GameMap.ts +++ b/front/src/Phaser/Game/GameMap.ts @@ -2,7 +2,7 @@ import type { ITiledMap, ITiledMapLayer, ITiledMapProperty } from "../Map/ITiled import { flattenGroupLayersMap } from "../Map/LayersFlattener"; import TilemapLayer = Phaser.Tilemaps.TilemapLayer; import { DEPTH_OVERLAY_INDEX } from "./DepthIndexes"; -import { iframeListener } from "../../Api/IframeListener"; +import { GameMapProperties } from "./GameMapProperties"; export type PropertyChangeCallback = ( newValue: string | number | boolean | undefined, @@ -59,12 +59,12 @@ export class GameMap { if (tile.properties) { this.tileSetPropertyMap[tileset.firstgid + tile.id] = tile.properties; tile.properties.forEach((prop) => { - if (prop.name == "name" && typeof prop.value == "string") { + if (prop.name == GameMapProperties.NAME && typeof prop.value == "string") { this.tileNameMap.set(prop.value, tileset.firstgid + tile.id); } - if (prop.name == "exitUrl" && typeof prop.value == "string") { + if (prop.name == GameMapProperties.EXIT_URL && typeof prop.value == "string") { this.exitUrls.push(prop.value); - } else if (prop.name == "start") { + } else if (prop.name == GameMapProperties.START) { this.hasStartTile = true; } }); @@ -304,7 +304,7 @@ export class GameMap { this.putTileInFlatLayer(tileIndex, x, y, layer); const phaserTile = phaserLayer.putTileAt(tileIndex, x, y); for (const property of this.getTileProperty(tileIndex)) { - if (property.name === "collides" && property.value) { + if (property.name === GameMapProperties.COLLIDES && property.value) { phaserTile.setCollision(true); } } diff --git a/front/src/Phaser/Game/GameMapProperties.ts b/front/src/Phaser/Game/GameMapProperties.ts new file mode 100644 index 00000000..d13f828a --- /dev/null +++ b/front/src/Phaser/Game/GameMapProperties.ts @@ -0,0 +1,37 @@ +export enum GameMapProperties { + ALLOW_API = 'allowApi', + AUDIO_LOOP = 'audioLoop', + AUDIO_VOLUME = 'audioVolume', + COLLIDES = 'collides', + DEFAULT = 'default', + EXIT_URL = 'exitUrl', + EXIT_SCENE_URL = 'exitSceneUrl', + FONT_FAMILY = 'font-family', + JITSI_ADMIN_ROOM_TAG = 'jitsiRoomAdminTag', + JITSI_CONFIG = 'jitsiConfig', + JITSI_INTERFACE_CONFIG = 'jitsiInterfaceConfig', + JITSI_ROOM = 'jitsiRoom', + JITSI_TRIGGER = 'jitsiTrigger', + JITSI_TRIGGER_MESSAGE = 'jitsiTriggerMessage', + JITSI_URL = 'jitsiUrl', + JITSI_WIDTH = 'jitsiWidth', + NAME = 'name', + OPEN_TAB = 'openTab', + OPEN_WEBSITE = 'openWebsite', + OPEN_WEBSITE_ALLOW_API = 'openWebsiteAllowApi', + OPEN_WEBSITE_POLICY = 'openWebsitePolicy', + OPEN_WEBSITE_WIDTH = 'openWebsiteWidth', + OPEN_WEBSITE_POSITION = 'openWebsitePosition', + OPEN_WEBSITE_TRIGGER = 'openWebsiteTrigger', + OPEN_WEBSITE_TRIGGER_MESSAGE = 'openWebsiteTriggerMessage', + PLAY_AUDIO = 'playAudio', + PLAY_AUDIO_LOOP = 'playAudioLoop', + READABLE_BY = 'readableBy', + SCRIPT = 'script', + SILENT = 'silent', + START = 'start', + START_LAYER = 'startLayer', + URL = 'url', + WRITABLE_BY = 'writableBy', + ZONE = 'zone', +} diff --git a/front/src/Phaser/Game/GameMapPropertiesListener.ts b/front/src/Phaser/Game/GameMapPropertiesListener.ts index 3ae6d714..5a033d5c 100644 --- a/front/src/Phaser/Game/GameMapPropertiesListener.ts +++ b/front/src/Phaser/Game/GameMapPropertiesListener.ts @@ -7,10 +7,9 @@ import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore"; import { get } from 'svelte/store'; import { ON_ACTION_TRIGGER_BUTTON, - TRIGGER_WEBSITE_PROPERTIES, - WEBSITE_MESSAGE_PROPERTIES, } from "../../WebRtc/LayoutManager"; import type { ITiledMapLayer } from "../Map/ITiledMap"; +import { GameMapProperties } from "./GameMapProperties"; enum OpenCoWebsiteState { LOADING, @@ -30,14 +29,14 @@ export class GameMapPropertiesListener { constructor(private scene: GameScene, private gameMap: GameMap) {} register() { - this.gameMap.onPropertyChange("openTab", (newValue, oldvalue, allProps) => { + this.gameMap.onPropertyChange(GameMapProperties.OPEN_TAB, (newValue, oldvalue, allProps) => { if (newValue === undefined) { layoutManagerActionStore.removeAction("openTab"); } if (typeof newValue == "string" && newValue.length) { - const openWebsiteTriggerValue = allProps.get(TRIGGER_WEBSITE_PROPERTIES); + const openWebsiteTriggerValue = allProps.get(GameMapProperties.OPEN_WEBSITE_TRIGGER); if (openWebsiteTriggerValue && openWebsiteTriggerValue === ON_ACTION_TRIGGER_BUTTON) { - let message = allProps.get(WEBSITE_MESSAGE_PROPERTIES); + let message = allProps.get(GameMapProperties.OPEN_WEBSITE_TRIGGER_MESSAGE); if (message === undefined) { message = "Press SPACE or touch here to open web site in new tab"; } @@ -72,25 +71,25 @@ export class GameMapPropertiesListener { layer.properties.forEach(property => { switch(property.name) { - case 'openWebsite': + case GameMapProperties.OPEN_WEBSITE: openWebsiteProperty = property.value as string | undefined; break; - case 'openWebsiteAllowApi': + case GameMapProperties.OPEN_WEBSITE_ALLOW_API: allowApiProperty = property.value as boolean | undefined; break; - case 'openWebsitePolicy': + case GameMapProperties.OPEN_WEBSITE_POLICY: websitePolicyProperty = property.value as string | undefined; break; - case 'openWebsiteWidth': + case GameMapProperties.OPEN_WEBSITE_WIDTH: websiteWidthProperty = property.value as number | undefined; break; - case 'openWebsitePosition': + case GameMapProperties.OPEN_WEBSITE_POSITION: websitePositionProperty = property.value as number | undefined; break; - case TRIGGER_WEBSITE_PROPERTIES: + case GameMapProperties.OPEN_WEBSITE_TRIGGER: websiteTriggerProperty = property.value as string | undefined; break; - case WEBSITE_MESSAGE_PROPERTIES: + case GameMapProperties.OPEN_WEBSITE_TRIGGER_MESSAGE: websiteTriggerMessageProperty = property.value as string | undefined; break; } @@ -172,10 +171,10 @@ export class GameMapPropertiesListener { layer.properties.forEach(property => { switch(property.name) { - case 'openWebsite': + case GameMapProperties.OPEN_WEBSITE: openWebsiteProperty = property.value as string | undefined; break; - case TRIGGER_WEBSITE_PROPERTIES: + case GameMapProperties.OPEN_WEBSITE_TRIGGER: websiteTriggerProperty = property.value as string | undefined; break; } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index c8858ad3..6091f4cc 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -16,14 +16,8 @@ import { DEBUG_MODE, JITSI_PRIVATE_MODE, MAX_PER_GROUP, POSITION_DELAY } from ". import { Queue } from "queue-typescript"; import { - AUDIO_LOOP_PROPERTY, - AUDIO_VOLUME_PROPERTY, Box, - JITSI_MESSAGE_PROPERTIES, ON_ACTION_TRIGGER_BUTTON, - TRIGGER_JITSI_PROPERTIES, - TRIGGER_WEBSITE_PROPERTIES, - WEBSITE_MESSAGE_PROPERTIES, } from "../../WebRtc/LayoutManager"; import { CoWebsite, coWebsiteManager } from "../../WebRtc/CoWebsiteManager"; import type { UserMovedMessage } from "../../Messages/generated/messages_pb"; @@ -96,6 +90,7 @@ import { GameMapPropertiesListener } from "./GameMapPropertiesListener"; import { analyticsClient } from "../../Administration/AnalyticsClient"; import { get } from "svelte/store"; import { contactPageStore } from "../../Stores/MenuStore"; +import { GameMapProperties } from "./GameMapProperties"; export interface GameSceneInitInterface { initPosition: PointInterface | null; @@ -498,11 +493,11 @@ export class GameScene extends DirtyScene { if (object.type === "website") { // Let's load iframes in the map const url = PropertyUtils.mustFindStringProperty( - "url", + GameMapProperties.URL, object.properties, 'in the "' + object.name + '" object of type "website"' ); - const allowApi = PropertyUtils.findBooleanProperty("allowApi", object.properties); + const allowApi = PropertyUtils.findBooleanProperty(GameMapProperties.ALLOW_API, object.properties); // TODO: add a "allow" property to iframe this.embeddedWebsiteManager.createEmbeddedWebsite( @@ -828,7 +823,7 @@ export class GameScene extends DirtyScene { } private triggerOnMapLayerPropertyChange() { - this.gameMap.onPropertyChange("exitSceneUrl", (newValue, oldValue) => { + this.gameMap.onPropertyChange(GameMapProperties.EXIT_SCENE_URL, (newValue, oldValue) => { if (newValue) { this.onMapExit( Room.getRoomPathFromExitSceneUrl(newValue as string, window.location.toString(), this.MapUrlFile) @@ -839,7 +834,7 @@ export class GameScene extends DirtyScene { }, 2000); } }); - this.gameMap.onPropertyChange("exitUrl", (newValue, oldValue) => { + this.gameMap.onPropertyChange(GameMapProperties.EXIT_URL, (newValue, oldValue) => { if (newValue) { this.onMapExit(Room.getRoomPathFromExitUrl(newValue as string, window.location.toString())); } else { @@ -849,16 +844,16 @@ export class GameScene extends DirtyScene { } }); - this.gameMap.onPropertyChange("jitsiRoom", (newValue, oldValue, allProps) => { + this.gameMap.onPropertyChange(GameMapProperties.JITSI_ROOM, (newValue, oldValue, allProps) => { if (newValue === undefined) { layoutManagerActionStore.removeAction("jitsi"); this.stopJitsi(); } else { const openJitsiRoomFunction = () => { const roomName = jitsiFactory.getRoomName(newValue.toString(), this.instance); - const jitsiUrl = allProps.get("jitsiUrl") as string | undefined; + const jitsiUrl = allProps.get(GameMapProperties.JITSI_URL) as string | undefined; if (JITSI_PRIVATE_MODE && !jitsiUrl) { - const adminTag = allProps.get("jitsiRoomAdminTag") as string | undefined; + const adminTag = allProps.get(GameMapProperties.JITSI_ADMIN_ROOM_TAG) as string | undefined; this.connection?.emitQueryJitsiJwtMessage(roomName, adminTag); } else { @@ -867,9 +862,9 @@ export class GameScene extends DirtyScene { layoutManagerActionStore.removeAction("jitsi"); }; - const jitsiTriggerValue = allProps.get(TRIGGER_JITSI_PROPERTIES); + const jitsiTriggerValue = allProps.get(GameMapProperties.JITSI_TRIGGER); if (jitsiTriggerValue && jitsiTriggerValue === ON_ACTION_TRIGGER_BUTTON) { - let message = allProps.get(JITSI_MESSAGE_PROPERTIES); + let message = allProps.get(GameMapProperties.JITSI_TRIGGER_MESSAGE); if (message === undefined) { message = "Press SPACE or touch here to enter Jitsi Meet room"; } @@ -885,7 +880,7 @@ export class GameScene extends DirtyScene { } } }); - this.gameMap.onPropertyChange("silent", (newValue, oldValue) => { + this.gameMap.onPropertyChange(GameMapProperties.SILENT, (newValue, oldValue) => { if (newValue === undefined || newValue === false || newValue === "") { this.connection?.setSilent(false); this.CurrentPlayer.noSilent(); @@ -894,16 +889,16 @@ export class GameScene extends DirtyScene { this.CurrentPlayer.isSilent(); } }); - this.gameMap.onPropertyChange("playAudio", (newValue, oldValue, allProps) => { - const volume = allProps.get(AUDIO_VOLUME_PROPERTY) as number | undefined; - const loop = allProps.get(AUDIO_LOOP_PROPERTY) as boolean | undefined; + this.gameMap.onPropertyChange(GameMapProperties.PLAY_AUDIO, (newValue, oldValue, allProps) => { + const volume = allProps.get(GameMapProperties.AUDIO_VOLUME) as number | undefined; + const loop = allProps.get(GameMapProperties.AUDIO_LOOP) as boolean | undefined; newValue === undefined ? audioManagerFileStore.unloadAudio() : audioManagerFileStore.playAudio(newValue, this.getMapDirUrl(), volume, loop); audioManagerVisibilityStore.set(!(newValue === undefined)); }); // TODO: This legacy property should be removed at some point - this.gameMap.onPropertyChange("playAudioLoop", (newValue, oldValue) => { + this.gameMap.onPropertyChange(GameMapProperties.PLAY_AUDIO_LOOP, (newValue, oldValue) => { newValue === undefined ? audioManagerFileStore.unloadAudio() : audioManagerFileStore.playAudio(newValue, this.getMapDirUrl(), undefined, true); @@ -911,7 +906,7 @@ export class GameScene extends DirtyScene { }); // TODO: Legacy functionnality replace by layer change - this.gameMap.onPropertyChange("zone", (newValue, oldValue) => { + this.gameMap.onPropertyChange(GameMapProperties.ZONE, (newValue, oldValue) => { if (oldValue) { iframeListener.sendLeaveEvent(oldValue as string); } @@ -1265,7 +1260,7 @@ ${escapedMessage} propertyName: string, propertyValue: string | number | boolean | undefined ): void { - if (propertyName === "exitUrl" && typeof propertyValue === "string") { + if (propertyName === GameMapProperties.EXIT_URL && typeof propertyValue === "string") { this.loadNextGameFromExitUrl(propertyValue); } this.gameMap.setLayerProperty(layerName, propertyName, propertyValue); @@ -1403,18 +1398,18 @@ ${escapedMessage} } private getExitUrl(layer: ITiledMapLayer): string | undefined { - return this.getProperty(layer, "exitUrl") as string | undefined; + return this.getProperty(layer, GameMapProperties.EXIT_URL) as string | undefined; } /** * @deprecated the map property exitSceneUrl is deprecated */ private getExitSceneUrl(layer: ITiledMapLayer): string | undefined { - return this.getProperty(layer, "exitSceneUrl") as string | undefined; + return this.getProperty(layer, GameMapProperties.EXIT_SCENE_URL) as string | undefined; } private getScriptUrls(map: ITiledMap): string[] { - return (this.getProperties(map, "script") as string[]).map((script) => + return (this.getProperties(map, GameMapProperties.SCRIPT) as string[]).map((script) => new URL(script, this.MapUrlFile).toString() ); } @@ -1872,13 +1867,15 @@ ${escapedMessage} public startJitsi(roomName: string, jwt?: string): void { const allProps = this.gameMap.getCurrentProperties(); - const jitsiConfig = this.safeParseJSONstring(allProps.get("jitsiConfig") as string | undefined, "jitsiConfig"); - const jitsiInterfaceConfig = this.safeParseJSONstring( - allProps.get("jitsiInterfaceConfig") as string | undefined, - "jitsiInterfaceConfig" + const jitsiConfig = this.safeParseJSONstring( + allProps.get(GameMapProperties.JITSI_CONFIG) as string | undefined, GameMapProperties.JITSI_CONFIG ); - const jitsiUrl = allProps.get("jitsiUrl") as string | undefined; - const jitsiWidth = allProps.get("jitsiWidth") as number | undefined; + const jitsiInterfaceConfig = this.safeParseJSONstring( + allProps.get(GameMapProperties.JITSI_INTERFACE_CONFIG) as string | undefined, + GameMapProperties.JITSI_INTERFACE_CONFIG + ); + const jitsiUrl = allProps.get(GameMapProperties.JITSI_URL) as string | undefined; + const jitsiWidth = allProps.get(GameMapProperties.JITSI_WIDTH) as number | undefined; jitsiFactory.start(roomName, this.playerName, jwt, jitsiConfig, jitsiInterfaceConfig, jitsiUrl, jitsiWidth); this.connection?.setSilent(true); @@ -1892,7 +1889,7 @@ ${escapedMessage} } public stopJitsi(): void { - const silent = this.gameMap.getCurrentProperties().get("silent"); + const silent = this.gameMap.getCurrentProperties().get(GameMapProperties.SILENT); this.connection?.setSilent(!!silent); jitsiFactory.stop(); mediaManager.showGameOverlay(); diff --git a/front/src/Phaser/Game/SharedVariablesManager.ts b/front/src/Phaser/Game/SharedVariablesManager.ts index b4f2a3f7..8f913765 100644 --- a/front/src/Phaser/Game/SharedVariablesManager.ts +++ b/front/src/Phaser/Game/SharedVariablesManager.ts @@ -2,6 +2,7 @@ import type { RoomConnection } from "../../Connexion/RoomConnection"; import { iframeListener } from "../../Api/IframeListener"; import type { GameMap } from "./GameMap"; import type { ITiledMapLayer, ITiledMapObject, ITiledMapObjectLayer } from "../Map/ITiledMap"; +import { GameMapProperties } from "./GameMapProperties"; interface Variable { defaultValue: unknown; @@ -133,10 +134,10 @@ export class SharedVariablesManager { for (const property of object.properties) { const value = property.value; switch (property.name) { - case "default": + case GameMapProperties.DEFAULT: variable.defaultValue = value; break; - case "writableBy": + case GameMapProperties.WRITABLE_BY: if (typeof value !== "string") { throw new Error( 'The writableBy property of variable "' + object.name + '" must be a string' @@ -146,7 +147,7 @@ export class SharedVariablesManager { variable.writableBy = value; } break; - case "readableBy": + case GameMapProperties.READABLE_BY: if (typeof value !== "string") { throw new Error( 'The readableBy property of variable "' + object.name + '" must be a string' diff --git a/front/src/Phaser/Game/StartPositionCalculator.ts b/front/src/Phaser/Game/StartPositionCalculator.ts index a5f96314..5ae00a94 100644 --- a/front/src/Phaser/Game/StartPositionCalculator.ts +++ b/front/src/Phaser/Game/StartPositionCalculator.ts @@ -1,6 +1,7 @@ import type { PositionInterface } from "../../Connexion/ConnexionModels"; import type { ITiledMap, ITiledMapLayer, ITiledMapProperty, ITiledMapTileLayer } from "../Map/ITiledMap"; import type { GameMap } from "./GameMap"; +import { GameMapProperties } from "./GameMapProperties"; const defaultStartLayerName = "start"; @@ -76,7 +77,7 @@ export class StartPositionCalculator { } private isStartLayer(layer: ITiledMapLayer): boolean { - return this.getProperty(layer, "startLayer") == true; + return this.getProperty(layer, GameMapProperties.START_LAYER) == true; } /** diff --git a/front/src/WebRtc/LayoutManager.ts b/front/src/WebRtc/LayoutManager.ts index 0d9a4ba9..de79047f 100644 --- a/front/src/WebRtc/LayoutManager.ts +++ b/front/src/WebRtc/LayoutManager.ts @@ -14,13 +14,4 @@ export enum DivImportance { export const ON_ACTION_TRIGGER_BUTTON = "onaction"; -export const TRIGGER_WEBSITE_PROPERTIES = "openWebsiteTrigger"; -export const TRIGGER_JITSI_PROPERTIES = "jitsiTrigger"; - -export const WEBSITE_MESSAGE_PROPERTIES = "openWebsiteTriggerMessage"; -export const JITSI_MESSAGE_PROPERTIES = "jitsiTriggerMessage"; - -export const AUDIO_VOLUME_PROPERTY = "audioVolume"; -export const AUDIO_LOOP_PROPERTY = "audioLoop"; - export type Box = { xStart: number; yStart: number; xEnd: number; yEnd: number };