import { Subject } from "rxjs"; import { EnterLeaveEvent, isEnterLeaveEvent } from '../Events/EnterLeaveEvent'; import {IframeApiContribution, sendToWorkadventure} from './IframeApiContribution'; import { apiCallback } from "./registeredCallbacks"; import type {LayerEvent} from "../Events/LayerEvent"; import type {SetPropertyEvent} from "../Events/setPropertyEvent"; import type {GameStateEvent} from "../Events/GameStateEvent"; import type {ITiledMap} from "../../Phaser/Map/ITiledMap"; import type {DataLayerEvent} from "../Events/DataLayerEvent"; import {isGameStateEvent} from "../Events/GameStateEvent"; import {isDataLayerEvent} from "../Events/DataLayerEvent"; const enterStreams: Map> = new Map>(); const leaveStreams: Map> = new Map>(); const dataLayerResolver = new Subject(); const stateResolvers = new Subject(); let immutableData: GameStateEvent; interface Room { id: string, mapUrl: string, map: ITiledMap, startLayer: string | null } interface User { id: string | undefined, nickName: string | null, tags: string[] } function getGameState(): Promise { if (immutableData) { return Promise.resolve(immutableData); } else { return new Promise((resolver, thrower) => { stateResolvers.subscribe(resolver); sendToWorkadventure({type: "getState", data: null}); }) } } function getDataLayer(): Promise { return new Promise((resolver, thrower) => { dataLayerResolver.subscribe(resolver); sendToWorkadventure({type: "getDataLayer", data: null}) }) } class WorkadventureRoomCommands extends IframeApiContribution { callbacks = [ apiCallback({ callback: (payloadData: EnterLeaveEvent) => { enterStreams.get(payloadData.name)?.next(); }, type: "enterEvent", typeChecker: isEnterLeaveEvent }), apiCallback({ type: "leaveEvent", typeChecker: isEnterLeaveEvent, callback: (payloadData) => { leaveStreams.get(payloadData.name)?.next(); } }), apiCallback({ type: "gameState", typeChecker: isGameStateEvent, callback: (payloadData) => { stateResolvers.next(payloadData); } }), apiCallback({ type: "dataLayer", typeChecker: isDataLayerEvent, callback: (payloadData) => { dataLayerResolver.next(payloadData); } }), ] onEnterZone(name: string, callback: () => void): void { let subject = enterStreams.get(name); if (subject === undefined) { subject = new Subject(); enterStreams.set(name, subject); } subject.subscribe(callback); } onLeaveZone(name: string, callback: () => void): void { let subject = leaveStreams.get(name); if (subject === undefined) { subject = new Subject(); leaveStreams.set(name, subject); } subject.subscribe(callback); } showLayer(layerName: string): void { sendToWorkadventure({type: 'showLayer', data: {'name': layerName} as LayerEvent}); } hideLayer(layerName: string): void { sendToWorkadventure({type: 'hideLayer', data: {'name': layerName} as LayerEvent}); } setProperty(layerName: string, propertyName: string, propertyValue: string | number | boolean | undefined): void { sendToWorkadventure({ type: 'setProperty', data: { 'layerName': layerName, 'propertyName': propertyName, 'propertyValue': propertyValue, } as SetPropertyEvent }) } getCurrentRoom(): Promise { return getGameState().then((gameState) => { return getDataLayer().then((mapJson) => { return {id: gameState.roomId, map: mapJson.data as ITiledMap, mapUrl: gameState.mapUrl, startLayer: gameState.startLayerName}; }) }) } getCurrentUser(): Promise { return getGameState().then((gameState) => { return {id: gameState.uuid, nickName: gameState.nickname, tags: gameState.tags}; }) } } export default new WorkadventureRoomCommands();