From 89cd292527e711abe26193b8d822dc76ab80d5d8 Mon Sep 17 00:00:00 2001 From: Benedicte Quimbert Date: Fri, 15 Oct 2021 17:01:38 +0200 Subject: [PATCH] Allows to read and write "Player properties" from LocalStorage --- front/src/Api/Events/IframeEvent.ts | 11 ++++++++++- front/src/Api/Events/PlayerPropertyEvent.ts | 13 +++++++++++++ front/src/Api/iframe/player.ts | 17 ++++++++++++++++- front/src/Connexion/LocalUserStore.ts | 9 ++++++++- front/src/Phaser/Game/GameScene.ts | 13 +++++++++++++ 5 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 front/src/Api/Events/PlayerPropertyEvent.ts diff --git a/front/src/Api/Events/IframeEvent.ts b/front/src/Api/Events/IframeEvent.ts index 081008c4..9c491d3a 100644 --- a/front/src/Api/Events/IframeEvent.ts +++ b/front/src/Api/Events/IframeEvent.ts @@ -28,6 +28,7 @@ import type { MessageReferenceEvent } from "./ui/TriggerActionMessageEvent"; import { isMessageReferenceEvent, isTriggerActionMessageEvent } from "./ui/TriggerActionMessageEvent"; import type { MenuRegisterEvent, UnregisterMenuEvent } from "./ui/MenuRegisterEvent"; import type { ChangeLayerEvent } from "./ChangeLayerEvent"; +import { isPlayerPropertyEvent } from "./PlayerPropertyEvent"; export interface TypedMessageEvent extends MessageEvent { data: T; @@ -59,7 +60,7 @@ export type IframeEventMap = { registerMenu: MenuRegisterEvent; unregisterMenu: UnregisterMenuEvent; setTiles: SetTilesEvent; - modifyEmbeddedWebsite: Partial; // Note: name should be compulsory in fact + modifyEmbeddedWebsite: Partial; // Note: name should be compulsory in fact; }; export interface IframeEvent { type: T; @@ -149,6 +150,14 @@ export const iframeQueryMapTypeGuards = { query: isCreateEmbeddedWebsiteEvent, answer: tg.isUndefined, }, + getPlayerProperty: { + query: tg.isString, + answer: isPlayerPropertyEvent, + }, + setPlayerProperty: { + query: isPlayerPropertyEvent, + answer: tg.isUndefined, + }, }; type GuardedType = T extends (x: unknown) => x is infer T ? T : never; diff --git a/front/src/Api/Events/PlayerPropertyEvent.ts b/front/src/Api/Events/PlayerPropertyEvent.ts new file mode 100644 index 00000000..fe85d9ea --- /dev/null +++ b/front/src/Api/Events/PlayerPropertyEvent.ts @@ -0,0 +1,13 @@ +import * as tg from "generic-type-guard"; + +export const isPlayerPropertyEvent = new tg.IsInterface() + .withProperties({ + propertyName: tg.isString, + propertyValue: tg.isUnknown, + }) + .get(); + +/** + * A message sent from the iFrame to set player-related properties. + */ +export type PlayerPropertyEvent = tg.GuardedType; diff --git a/front/src/Api/iframe/player.ts b/front/src/Api/iframe/player.ts index 078a1926..f97705f0 100644 --- a/front/src/Api/iframe/player.ts +++ b/front/src/Api/iframe/player.ts @@ -1,8 +1,9 @@ -import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribution"; +import { IframeApiContribution, queryWorkadventure, sendToWorkadventure } from "./IframeApiContribution"; import type { HasPlayerMovedEvent, HasPlayerMovedEventCallback } from "../Events/HasPlayerMovedEvent"; import { Subject } from "rxjs"; import { apiCallback } from "./registeredCallbacks"; import { isHasPlayerMovedEvent } from "../Events/HasPlayerMovedEvent"; +import type { PlayerPropertyEvent } from "../Events/PlayerPropertyEvent"; const moveStream = new Subject(); @@ -67,6 +68,20 @@ export class WorkadventurePlayerCommands extends IframeApiContribution { + return queryWorkadventure({ + type: "getPlayerProperty", + data: name, + }); + } + + setPlayerProperty(property: PlayerPropertyEvent) { + queryWorkadventure({ + type: "setPlayerProperty", + data: property, + }).catch((e) => console.error(e)); + } } export default new WorkadventurePlayerCommands(); diff --git a/front/src/Connexion/LocalUserStore.ts b/front/src/Connexion/LocalUserStore.ts index ac57c3c7..49663346 100644 --- a/front/src/Connexion/LocalUserStore.ts +++ b/front/src/Connexion/LocalUserStore.ts @@ -20,8 +20,8 @@ const nonce = "nonce"; const notification = "notificationPermission"; const code = "code"; const cameraSetup = "cameraSetup"; - const cacheAPIIndex = "workavdenture-cache"; +const userProperties = "user-properties"; class LocalUserStore { saveUser(localUser: LocalUser) { @@ -204,6 +204,13 @@ class LocalUserStore { const cameraSetupValues = localStorage.getItem(cameraSetup); return cameraSetupValues != undefined ? JSON.parse(cameraSetupValues) : undefined; } + getUserProperty(name: string): string | null { + return localStorage.getItem(userProperties + "_" + name); + } + + setUserProperty(name: string, value: string): void { + localStorage.setItem(userProperties + "_" + name, value); + } } export const localUserStore = new LocalUserStore(); diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index d9bb8186..5a1407a0 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -1153,6 +1153,19 @@ ${escapedMessage} }; }); + //TODO : move Player Properties related-code + iframeListener.registerAnswerer("setPlayerProperty", (event) => { + localUserStore.setUserProperty(event.propertyName, event.propertyValue as string); + }); + + iframeListener.registerAnswerer("getPlayerProperty", (event) => { + return { + propertyName: event, + propertyValue: localUserStore.getUserProperty(event), + }; + }); + //END TODO + iframeListener.registerAnswerer("getState", async () => { // The sharedVariablesManager is not instantiated before the connection is established. So we need to wait // for the connection to send back the answer.