From 7971daa27fa0a7d188f5a2a6f3e3a611a2ba3054 Mon Sep 17 00:00:00 2001 From: jonny Date: Wed, 1 Sep 2021 14:50:48 +0200 Subject: [PATCH 1/4] openTabPropertyKey (create new props in own file) --- .../src/Phaser/Game/GameMapPropertyChange.ts | 56 +++++++++++++++++++ front/src/Phaser/Game/GameScene.ts | 34 +---------- 2 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 front/src/Phaser/Game/GameMapPropertyChange.ts diff --git a/front/src/Phaser/Game/GameMapPropertyChange.ts b/front/src/Phaser/Game/GameMapPropertyChange.ts new file mode 100644 index 00000000..929b94c8 --- /dev/null +++ b/front/src/Phaser/Game/GameMapPropertyChange.ts @@ -0,0 +1,56 @@ +import type { GameScene } from "./GameScene"; +import type { GameMap } from "./GameMap"; +import { scriptUtils } from "../../Api/ScriptUtils"; +import { coWebsiteManager } from "../../WebRtc/CoWebsiteManager"; +import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore"; +import { + ON_ACTION_TRIGGER_BUTTON, + TRIGGER_WEBSITE_PROPERTIES, + WEBSITE_MESSAGE_PROPERTIES, +} from "../../WebRtc/LayoutManager"; + +export class GameMapPropertyChange { + constructor(private scene: GameScene, private gameMap: GameMap) {} + + register() { + this.gameMap.onPropertyChange("openTab", (newValue) => { + if (typeof newValue == "string" && newValue.length) { + scriptUtils.openTab(newValue); + } + }); + + this.gameMap.onPropertyChange("openWebsite", (newValue, oldValue, allProps) => { + if (newValue === undefined) { + layoutManagerActionStore.removeAction("openWebsite"); + coWebsiteManager.closeCoWebsite(); + } else { + const openWebsiteFunction = () => { + coWebsiteManager.loadCoWebsite( + newValue as string, + this.scene.MapUrlFile, + allProps.get("openWebsiteAllowApi") as boolean | undefined, + allProps.get("openWebsitePolicy") as string | undefined + ); + layoutManagerActionStore.removeAction("openWebsite"); + }; + + const openWebsiteTriggerValue = allProps.get(TRIGGER_WEBSITE_PROPERTIES); + if (openWebsiteTriggerValue && openWebsiteTriggerValue === ON_ACTION_TRIGGER_BUTTON) { + let message = allProps.get(WEBSITE_MESSAGE_PROPERTIES); + if (message === undefined) { + message = "Press SPACE or touch here to open web site"; + } + layoutManagerActionStore.addAction({ + uuid: "openWebsite", + type: "message", + message: message, + callback: () => openWebsiteFunction(), + userInputManager: this.scene.userInputManager, + }); + } else { + openWebsiteFunction(); + } + } + }); + } +} diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 7ba97175..9ab097c5 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -92,6 +92,7 @@ import Tileset = Phaser.Tilemaps.Tileset; import { userIsAdminStore } from "../../Stores/GameStore"; import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore"; import { EmbeddedWebsiteManager } from "./EmbeddedWebsiteManager"; +import { GameMapPropertyChange } from "./GameMapPropertyChange"; export interface GameSceneInitInterface { initPosition: PointInterface | null; @@ -580,6 +581,7 @@ export class GameScene extends DirtyScene { this.updateCameraOffset(box) ); + new GameMapPropertyChange(this, this.gameMap).register(); this.triggerOnMapLayerPropertyChange(); if (!this.room.isDisconnected()) { @@ -825,39 +827,7 @@ export class GameScene extends DirtyScene { }, 2000); } }); - this.gameMap.onPropertyChange("openWebsite", (newValue, oldValue, allProps) => { - if (newValue === undefined) { - layoutManagerActionStore.removeAction("openWebsite"); - coWebsiteManager.closeCoWebsite(); - } else { - const openWebsiteFunction = () => { - coWebsiteManager.loadCoWebsite( - newValue as string, - this.MapUrlFile, - allProps.get("openWebsiteAllowApi") as boolean | undefined, - allProps.get("openWebsitePolicy") as string | undefined - ); - layoutManagerActionStore.removeAction("openWebsite"); - }; - const openWebsiteTriggerValue = allProps.get(TRIGGER_WEBSITE_PROPERTIES); - if (openWebsiteTriggerValue && openWebsiteTriggerValue === ON_ACTION_TRIGGER_BUTTON) { - let message = allProps.get(WEBSITE_MESSAGE_PROPERTIES); - if (message === undefined) { - message = "Press SPACE or touch here to open web site"; - } - layoutManagerActionStore.addAction({ - uuid: "openWebsite", - type: "message", - message: message, - callback: () => openWebsiteFunction(), - userInputManager: this.userInputManager, - }); - } else { - openWebsiteFunction(); - } - } - }); this.gameMap.onPropertyChange("jitsiRoom", (newValue, oldValue, allProps) => { if (newValue === undefined) { layoutManagerActionStore.removeAction("jitsi"); From 181232c1e678527b06d53f6a0373055660b460f4 Mon Sep 17 00:00:00 2001 From: jonny Date: Wed, 1 Sep 2021 17:55:23 +0200 Subject: [PATCH 2/4] added jitsiTypes --- front/src/WebRtc/JitsiFactory.ts | 33 +++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/front/src/WebRtc/JitsiFactory.ts b/front/src/WebRtc/JitsiFactory.ts index 7a3264f1..8e3a37c7 100644 --- a/front/src/WebRtc/JitsiFactory.ts +++ b/front/src/WebRtc/JitsiFactory.ts @@ -1,9 +1,7 @@ import { JITSI_URL } from "../Enum/EnvironmentVariable"; -import { mediaManager } from "./MediaManager"; import { coWebsiteManager } from "./CoWebsiteManager"; import { requestedCameraState, requestedMicrophoneState } from "../Stores/MediaStore"; import { get } from "svelte/store"; -declare const window: any; // eslint-disable-line @typescript-eslint/no-explicit-any interface jitsiConfigInterface { startWithAudioMuted: boolean; @@ -11,6 +9,32 @@ interface jitsiConfigInterface { prejoinPageEnabled: boolean; } +interface JitsiOptions { + jwt?: string; + roomName: string; + width: string; + height: string; + parentNode: HTMLElement; + configOverwrite: jitsiConfigInterface; + interfaceConfigOverwrite: typeof defaultInterfaceConfig; + onload?: Function; +} + +interface JitsiApi { + executeCommand: (command: string, ...args: Array) => void; + + addListener: (type: string, callback: Function) => void; + removeListener: (type: string, callback: Function) => void; + + dispose: () => void; +} + +declare global { + interface Window { + JitsiMeetExternalAPI: new (domain: string, options: JitsiOptions) => JitsiApi; + } +} + const getDefaultConfig = (): jitsiConfigInterface => { return { startWithAudioMuted: !get(requestedMicrophoneState), @@ -96,7 +120,7 @@ const slugify = (...args: (string | number)[]): string => { }; class JitsiFactory { - private jitsiApi: any; // eslint-disable-line @typescript-eslint/no-explicit-any + private jitsiApi?: JitsiApi; private audioCallback = this.onAudioChange.bind(this); private videoCallback = this.onVideoChange.bind(this); private jitsiScriptLoaded: boolean = false; @@ -132,8 +156,7 @@ class JitsiFactory { } await this.loadJitsiScript(domain); - const options: any = { - // eslint-disable-line @typescript-eslint/no-explicit-any + const options: JitsiOptions = { roomName: roomName, jwt: jwt, width: "100%", From 606e9093e15a78b29b4249b0afd9fdc5ea6d2df4 Mon Sep 17 00:00:00 2001 From: jonny Date: Wed, 1 Sep 2021 18:16:31 +0200 Subject: [PATCH 3/4] renamed --- ...{GameMapPropertyChange.ts => GameMapPropertiesListener.ts} | 2 +- front/src/Phaser/Game/GameScene.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename front/src/Phaser/Game/{GameMapPropertyChange.ts => GameMapPropertiesListener.ts} (98%) diff --git a/front/src/Phaser/Game/GameMapPropertyChange.ts b/front/src/Phaser/Game/GameMapPropertiesListener.ts similarity index 98% rename from front/src/Phaser/Game/GameMapPropertyChange.ts rename to front/src/Phaser/Game/GameMapPropertiesListener.ts index 76a7a3d4..db100935 100644 --- a/front/src/Phaser/Game/GameMapPropertyChange.ts +++ b/front/src/Phaser/Game/GameMapPropertiesListener.ts @@ -9,7 +9,7 @@ import { WEBSITE_MESSAGE_PROPERTIES, } from "../../WebRtc/LayoutManager"; -export class GameMapPropertyChange { +export class GameMapPropertiesListener { constructor(private scene: GameScene, private gameMap: GameMap) {} register() { diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index d29c5e3c..12063e6c 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -92,7 +92,7 @@ import Tileset = Phaser.Tilemaps.Tileset; import { userIsAdminStore } from "../../Stores/GameStore"; import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore"; import { EmbeddedWebsiteManager } from "./EmbeddedWebsiteManager"; -import { GameMapPropertyChange } from "./GameMapPropertyChange"; +import { GameMapPropertiesListener } from "./GameMapPropertiesListener"; export interface GameSceneInitInterface { initPosition: PointInterface | null; @@ -581,7 +581,7 @@ export class GameScene extends DirtyScene { this.updateCameraOffset(box) ); - new GameMapPropertyChange(this, this.gameMap).register(); + new GameMapPropertiesListener(this, this.gameMap).register(); this.triggerOnMapLayerPropertyChange(); if (!this.room.isDisconnected()) { From 68a47726272cc201c86b25c2773d5225c1ace958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Thu, 2 Sep 2021 17:29:29 +0200 Subject: [PATCH 4/4] Allowing variables nested in group layers Up until this commit, variables nested in object layers inside group layers where not found by the front nor the back. This PR changes analysis so that variables can be detected. --- back/package.json | 2 +- back/src/Services/VariablesManager.ts | 45 ++++++++++++------- back/yarn.lock | 8 ++-- .../src/Phaser/Game/SharedVariablesManager.ts | 42 +++++++++-------- 4 files changed, 58 insertions(+), 39 deletions(-) diff --git a/back/package.json b/back/package.json index 58399ad7..bb54d624 100644 --- a/back/package.json +++ b/back/package.json @@ -40,7 +40,7 @@ }, "homepage": "https://github.com/thecodingmachine/workadventure#readme", "dependencies": { - "@workadventure/tiled-map-type-guard": "^1.0.0", + "@workadventure/tiled-map-type-guard": "^1.0.2", "axios": "^0.21.1", "busboy": "^0.3.1", "circular-json": "^0.5.9", diff --git a/back/src/Services/VariablesManager.ts b/back/src/Services/VariablesManager.ts index e8aaef25..915c6c05 100644 --- a/back/src/Services/VariablesManager.ts +++ b/back/src/Services/VariablesManager.ts @@ -1,7 +1,12 @@ /** * Handles variables shared between the scripting API and the server. */ -import { ITiledMap, ITiledMapObject, ITiledMapObjectLayer } from "@workadventure/tiled-map-type-guard/dist"; +import { + ITiledMap, + ITiledMapLayer, + ITiledMapObject, + ITiledMapObjectLayer, +} from "@workadventure/tiled-map-type-guard/dist"; import { User } from "_Model/User"; import { variablesRepository } from "./Repository/VariablesRepository"; import { redisClient } from "./RedisClient"; @@ -83,25 +88,33 @@ export class VariablesManager { private static findVariablesInMap(map: ITiledMap): Map { const objects = new Map(); for (const layer of map.layers) { - if (layer.type === "objectgroup") { - for (const object of (layer as ITiledMapObjectLayer).objects) { - if (object.type === "variable") { - if (object.template) { - console.warn( - 'Warning, a variable object is using a Tiled "template". WorkAdventure does not support objects generated from Tiled templates.' - ); - continue; - } - - // We store a copy of the object (to make it immutable) - objects.set(object.name, this.iTiledObjectToVariable(object)); - } - } - } + this.recursiveFindVariablesInLayer(layer, objects); } return objects; } + private static recursiveFindVariablesInLayer(layer: ITiledMapLayer, objects: Map): void { + if (layer.type === "objectgroup") { + for (const object of layer.objects) { + if (object.type === "variable") { + if (object.template) { + console.warn( + 'Warning, a variable object is using a Tiled "template". WorkAdventure does not support objects generated from Tiled templates.' + ); + continue; + } + + // We store a copy of the object (to make it immutable) + objects.set(object.name, this.iTiledObjectToVariable(object)); + } + } + } else if (layer.type === "group") { + for (const innerLayer of layer.layers) { + this.recursiveFindVariablesInLayer(innerLayer, objects); + } + } + } + private static iTiledObjectToVariable(object: ITiledMapObject): Variable { const variable: Variable = {}; diff --git a/back/yarn.lock b/back/yarn.lock index 2265f4da..64dcb9ce 100644 --- a/back/yarn.lock +++ b/back/yarn.lock @@ -194,10 +194,10 @@ semver "^7.3.2" tsutils "^3.17.1" -"@workadventure/tiled-map-type-guard@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@workadventure/tiled-map-type-guard/-/tiled-map-type-guard-1.0.0.tgz#02524602ee8b2688429a1f56df1d04da3fc171ba" - integrity sha512-Mc0SE128otQnYlScQWVaQVyu1+CkailU/FTBh09UTrVnBAhyMO+jIn9vT9+Dv244xq+uzgQDpXmiVdjgrYFQ+A== +"@workadventure/tiled-map-type-guard@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@workadventure/tiled-map-type-guard/-/tiled-map-type-guard-1.0.2.tgz#4171550f6cd71be19791faef48360d65d698bcb0" + integrity sha512-RCtygGV5y9cb7QoyGMINBE9arM5pyXjkxvXgA5uXEv4GDbXKorhFim/rHgwbVR+eFnVF3rDgWbRnk3DIaHt+lQ== dependencies: generic-type-guard "^3.4.1" diff --git a/front/src/Phaser/Game/SharedVariablesManager.ts b/front/src/Phaser/Game/SharedVariablesManager.ts index 6a06d97e..76b78d04 100644 --- a/front/src/Phaser/Game/SharedVariablesManager.ts +++ b/front/src/Phaser/Game/SharedVariablesManager.ts @@ -1,10 +1,7 @@ import type { RoomConnection } from "../../Connexion/RoomConnection"; import { iframeListener } from "../../Api/IframeListener"; -import type { Subscription } from "rxjs"; import type { GameMap } from "./GameMap"; -import type { ITile, ITiledMapObject } from "../Map/ITiledMap"; -import type { Var } from "svelte/types/compiler/interfaces"; -import { init } from "svelte/internal"; +import type {ITiledMapLayer, ITiledMapObject, ITiledMapObjectLayer} from "../Map/ITiledMap"; interface Variable { defaultValue: unknown; @@ -100,24 +97,33 @@ export class SharedVariablesManager { private static findVariablesInMap(gameMap: GameMap): Map { const objects = new Map(); for (const layer of gameMap.getMap().layers) { - if (layer.type === "objectgroup") { - for (const object of layer.objects) { - if (object.type === "variable") { - if (object.template) { - console.warn( - 'Warning, a variable object is using a Tiled "template". WorkAdventure does not support objects generated from Tiled templates.' - ); - } - - // We store a copy of the object (to make it immutable) - objects.set(object.name, this.iTiledObjectToVariable(object)); - } - } - } + this.recursiveFindVariablesInLayer(layer, objects); } return objects; } + private static recursiveFindVariablesInLayer(layer: ITiledMapLayer, objects: Map): void { + if (layer.type === "objectgroup") { + for (const object of layer.objects) { + if (object.type === "variable") { + if (object.template) { + console.warn( + 'Warning, a variable object is using a Tiled "template". WorkAdventure does not support objects generated from Tiled templates.' + ); + continue; + } + + // We store a copy of the object (to make it immutable) + objects.set(object.name, this.iTiledObjectToVariable(object)); + } + } + } else if (layer.type === "group") { + for (const innerLayer of layer.layers) { + this.recursiveFindVariablesInLayer(innerLayer, objects); + } + } + } + private static iTiledObjectToVariable(object: ITiledMapObject): Variable { const variable: Variable = { defaultValue: undefined,