From f4df12e5ff898b3ba51b9568c09a0253de023ca9 Mon Sep 17 00:00:00 2001 From: Alexis Faizeau Date: Fri, 29 Oct 2021 16:47:19 +0200 Subject: [PATCH] Cowebsite properties manage by layer and not by property index --- .../Phaser/Game/GameMapPropertiesListener.ts | 195 ++++++++++++++++-- 1 file changed, 174 insertions(+), 21 deletions(-) diff --git a/front/src/Phaser/Game/GameMapPropertiesListener.ts b/front/src/Phaser/Game/GameMapPropertiesListener.ts index 29084d2a..3ae6d714 100644 --- a/front/src/Phaser/Game/GameMapPropertiesListener.ts +++ b/front/src/Phaser/Game/GameMapPropertiesListener.ts @@ -1,15 +1,32 @@ import type { GameScene } from "./GameScene"; import type { GameMap } from "./GameMap"; import { scriptUtils } from "../../Api/ScriptUtils"; +import type { CoWebsite } from "../../WebRtc/CoWebsiteManager"; import { coWebsiteManager } from "../../WebRtc/CoWebsiteManager"; 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"; + +enum OpenCoWebsiteState { + LOADING, + OPENED, + MUST_BE_CLOSE, +} + +interface OpenCoWebsite { + coWebsite: CoWebsite | undefined, + state: OpenCoWebsiteState +} export class GameMapPropertiesListener { + private coWebsitesOpenByLayer = new Map(); + private coWebsitesActionTriggerByLayer = new Map(); + constructor(private scene: GameScene, private gameMap: GameMap) {} register() { @@ -36,42 +53,178 @@ export class GameMapPropertiesListener { } } }); - this.gameMap.onPropertyChange("openWebsite", (newValue, oldValue, allProps) => { - const handler = async () => { - if (newValue === undefined || newValue !== oldValue) { - layoutManagerActionStore.removeAction("openWebsite"); - await coWebsiteManager.closeCoWebsites(); - } - if (newValue !== undefined) { + // Open a new co-website by the property. + this.gameMap.onEnterLayer((newLayers) => { + const handler = () => { + newLayers.forEach(layer => { + if (!layer.properties) { + return; + } + + let openWebsiteProperty: string | undefined; + let allowApiProperty: boolean | undefined; + let websitePolicyProperty: string | undefined; + let websiteWidthProperty: number | undefined; + let websitePositionProperty: number | undefined; + let websiteTriggerProperty: string | undefined; + let websiteTriggerMessageProperty: string | undefined; + + layer.properties.forEach(property => { + switch(property.name) { + case 'openWebsite': + openWebsiteProperty = property.value as string | undefined; + break; + case 'openWebsiteAllowApi': + allowApiProperty = property.value as boolean | undefined; + break; + case 'openWebsitePolicy': + websitePolicyProperty = property.value as string | undefined; + break; + case 'openWebsiteWidth': + websiteWidthProperty = property.value as number | undefined; + break; + case 'openWebsitePosition': + websitePositionProperty = property.value as number | undefined; + break; + case TRIGGER_WEBSITE_PROPERTIES: + websiteTriggerProperty = property.value as string | undefined; + break; + case WEBSITE_MESSAGE_PROPERTIES: + websiteTriggerMessageProperty = property.value as string | undefined; + break; + } + }); + + if (!openWebsiteProperty) { + return; + } + + const actionUuid = "openWebsite-" + (Math.random() + 1).toString(36).substring(7); + + if (this.coWebsitesOpenByLayer.has(layer)) { + return; + } + + this.coWebsitesOpenByLayer.set(layer, { + coWebsite: undefined, + state: OpenCoWebsiteState.LOADING, + }); + const openWebsiteFunction = () => { coWebsiteManager.loadCoWebsite( - newValue as string, + openWebsiteProperty as string, this.scene.MapUrlFile, - allProps.get("openWebsiteAllowApi") as boolean | undefined, - allProps.get("openWebsitePolicy") as string | undefined, - allProps.get("openWebsiteWidth") as number | undefined - ); + allowApiProperty, + websitePolicyProperty, + websiteWidthProperty, + websitePositionProperty, + ).then(coWebsite => { + const coWebsiteOpen = this.coWebsitesOpenByLayer.get(layer); + if (coWebsiteOpen && coWebsiteOpen.state === OpenCoWebsiteState.MUST_BE_CLOSE) { + coWebsiteManager.closeCoWebsite(coWebsite); + this.coWebsitesOpenByLayer.delete(layer); + this.coWebsitesActionTriggerByLayer.delete(layer); + } else { + this.coWebsitesOpenByLayer.set(layer, { + coWebsite, + state: OpenCoWebsiteState.OPENED + }); + } + }); - layoutManagerActionStore.removeAction("openWebsite"); + layoutManagerActionStore.removeAction(actionUuid); }; - 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"; + + if (websiteTriggerProperty && websiteTriggerProperty === ON_ACTION_TRIGGER_BUTTON) { + if (!websiteTriggerMessageProperty) { + websiteTriggerMessageProperty = "Press SPACE or touch here to open web site"; } + + this.coWebsitesActionTriggerByLayer.set(layer, actionUuid); + layoutManagerActionStore.addAction({ - uuid: "openWebsite", + uuid: actionUuid, type: "message", - message: message, + message: websiteTriggerMessageProperty, callback: () => openWebsiteFunction(), userInputManager: this.scene.userInputManager, }); } else { openWebsiteFunction(); } - } + }); + }; + + handler(); + }); + + // Close opened co-websites on leave the layer who contain the property. + this.gameMap.onLeaveLayer((oldLayers) => { + const handler = () => { + oldLayers.forEach(layer => { + if (!layer.properties) { + return; + } + + let openWebsiteProperty: string | undefined; + let websiteTriggerProperty: string | undefined; + + layer.properties.forEach(property => { + switch(property.name) { + case 'openWebsite': + openWebsiteProperty = property.value as string | undefined; + break; + case TRIGGER_WEBSITE_PROPERTIES: + websiteTriggerProperty = property.value as string | undefined; + break; + } + }); + + if (!openWebsiteProperty) { + return; + } + + const coWebsiteOpen = this.coWebsitesOpenByLayer.get(layer); + + if (!coWebsiteOpen) { + return; + } + + if (coWebsiteOpen.state === OpenCoWebsiteState.LOADING) { + coWebsiteOpen.state = OpenCoWebsiteState.MUST_BE_CLOSE; + return; + } + + if (coWebsiteOpen.state !== OpenCoWebsiteState.OPENED) { + return; + } + + if (coWebsiteOpen.coWebsite !== undefined) { + coWebsiteManager.closeCoWebsite(coWebsiteOpen.coWebsite); + } + + this.coWebsitesOpenByLayer.delete(layer); + + if (!websiteTriggerProperty) { + return; + } + + const actionStore = get(layoutManagerActionStore); + const actionTriggerUuid = this.coWebsitesActionTriggerByLayer.get(layer); + + if (!actionTriggerUuid) { + return; + } + + const action = actionStore && actionStore.length > 0 ? + actionStore.find(action => action.uuid === actionTriggerUuid) : undefined; + + + if (action) { + layoutManagerActionStore.removeAction(actionTriggerUuid); + } + }); }; handler();