diff --git a/docs/maps/api-reference.md b/docs/maps/api-reference.md index 9891a88a..b9525d3c 100644 --- a/docs/maps/api-reference.md +++ b/docs/maps/api-reference.md @@ -187,6 +187,26 @@ Example: WA.goToPage('https://www.wikipedia.org/'); ``` +### Going to a different map from the script + +``` + +goToRoom(url: string): void +``` + +Load the map at url without unloading workadventure + +relative urls: "../subFolder/map.json[#start-layer-name]" +global urls: "/_/global/domain/path/map.json[#start-layer-name]" + +Example: + +```javascript +WA.goToRoom("/@/tcm/workadventure/floor0") // workadventure urls +WA.goToRoom('../otherMap/map.json'); +WA.goToRoom("/_/global/.json#start-layer-2") +``` + ### Opening/closing a web page in an iFrame ``` diff --git a/front/src/Api/Events/IframeEvent.ts b/front/src/Api/Events/IframeEvent.ts index 67a30027..33de9675 100644 --- a/front/src/Api/Events/IframeEvent.ts +++ b/front/src/Api/Events/IframeEvent.ts @@ -5,11 +5,12 @@ import type { ChatEvent } from './ChatEvent'; import type { ClosePopupEvent } from './ClosePopupEvent'; import type { EnterLeaveEvent } from './EnterLeaveEvent'; import type { GoToPageEvent } from './GoToPageEvent'; +import type { LoadPageEvent } from './LoadPageEvent'; import type { OpenCoWebSiteEvent } from './OpenCoWebSiteEvent'; import type { OpenPopupEvent } from './OpenPopupEvent'; import type { OpenTabEvent } from './OpenTabEvent'; import type { UserInputChatEvent } from './UserInputChatEvent'; -import type {LoadSoundEvent} from "./LoadSoundEvent"; +import type { LoadSoundEvent} from "./LoadSoundEvent"; import type {PlaySoundEvent} from "./PlaySoundEvent"; @@ -20,6 +21,7 @@ export interface TypedMessageEvent extends MessageEvent { export type IframeEventMap = { //getState: GameStateEvent, // updateTile: UpdateTileEvent + loadPage: LoadPageEvent chat: ChatEvent, openPopup: OpenPopupEvent closePopup: ClosePopupEvent diff --git a/front/src/Api/Events/LoadPageEvent.ts b/front/src/Api/Events/LoadPageEvent.ts new file mode 100644 index 00000000..6f8b9bcf --- /dev/null +++ b/front/src/Api/Events/LoadPageEvent.ts @@ -0,0 +1,13 @@ +import * as tg from "generic-type-guard"; + + + +export const isLoadPageEvent = + new tg.IsInterface().withProperties({ + url: tg.isString, + }).get(); + +/** + * A message sent from the iFrame to the game to add a message in the chat. + */ +export type LoadPageEvent = tg.GuardedType; diff --git a/front/src/Api/IframeListener.ts b/front/src/Api/IframeListener.ts index 6c3afa31..232502a1 100644 --- a/front/src/Api/IframeListener.ts +++ b/front/src/Api/IframeListener.ts @@ -12,6 +12,7 @@ import { GoToPageEvent, isGoToPageEvent } from "./Events/GoToPageEvent"; import { isOpenCoWebsite, OpenCoWebSiteEvent } from "./Events/OpenCoWebSiteEvent"; import { IframeEventMap, IframeEvent, IframeResponseEvent, IframeResponseEventMap, isIframeEventWrapper, TypedMessageEvent } from "./Events/IframeEvent"; import type { UserInputChatEvent } from "./Events/UserInputChatEvent"; +import { isLoadPageEvent } from './Events/LoadPageEvent'; import {isPlaySoundEvent, PlaySoundEvent} from "./Events/PlaySoundEvent"; import {isStopSoundEvent, StopSoundEvent} from "./Events/StopSoundEvent"; import {isLoadSoundEvent, LoadSoundEvent} from "./Events/LoadSoundEvent"; @@ -32,6 +33,10 @@ class IframeListener { private readonly _goToPageStream: Subject = new Subject(); public readonly goToPageStream = this._goToPageStream.asObservable(); + + private readonly _loadPageStream: Subject = new Subject(); + public readonly loadPageStream = this._loadPageStream.asObservable(); + private readonly _openCoWebSiteStream: Subject = new Subject(); public readonly openCoWebSiteStream = this._openCoWebSiteStream.asObservable(); @@ -132,6 +137,8 @@ class IframeListener { } else if (payload.type === 'removeBubble') { this._removeBubbleStream.next(); + }else if (payload.type === 'loadPage' && isLoadPageEvent(payload.data)){ + this._loadPageStream.next(payload.data.url); } } diff --git a/front/src/Api/iframe/Navigation.ts b/front/src/Api/iframe/Navigation.ts index fe3fed8e..817d86c0 100644 --- a/front/src/Api/iframe/Navigation.ts +++ b/front/src/Api/iframe/Navigation.ts @@ -1,6 +1,7 @@ import type { GoToPageEvent } from '../Events/GoToPageEvent'; import type { OpenTabEvent } from '../Events/OpenTabEvent'; import { IframeApiContribution, sendToWorkadventure } from './IframeApiContribution'; +import {LoadPageEvent} from "../Events/LoadPageEvent"; @@ -29,7 +30,16 @@ class WorkadventureNavigationCommands extends IframeApiContribution{ this.userInputManager.restoreControls(); })); - + this.iframeSubscriptionList.push(iframeListener.loadPageStream.subscribe((url:string)=>{ + this.loadNextGame(url).then(()=>{ + this.events.once(EVENT_TYPE.POST_UPDATE,()=>{ + this.onMapExit(url); + }) + }) + })); let scriptedBubbleSprite : Sprite; this.iframeSubscriptionList.push(iframeListener.displayBubbleStream.subscribe(()=>{ scriptedBubbleSprite = new Sprite(this,this.CurrentPlayer.x + 25,this.CurrentPlayer.y,'circleSprite-white'); @@ -1095,10 +1102,10 @@ ${escapedMessage} } //todo: push that into the gameManager - private loadNextGame(exitSceneIdentifier: string): void { + private loadNextGame(exitSceneIdentifier: string): Promise { const {roomId, hash} = Room.getIdFromIdentifier(exitSceneIdentifier, this.MapUrlFile, this.instance); const room = new Room(roomId); - gameManager.loadMap(room, this.scene).catch(() => {}); + return gameManager.loadMap(room, this.scene).catch(() => {}); } private startUser(layer: ITiledMapTileLayer): PositionInterface { diff --git a/front/src/iframe_api.ts b/front/src/iframe_api.ts index f4888ec4..e6757f45 100644 --- a/front/src/iframe_api.ts +++ b/front/src/iframe_api.ts @@ -63,4 +63,4 @@ window.addEventListener('message', (mess } // ... -}); \ No newline at end of file +}); diff --git a/maps/tests/goToPageScript.js b/maps/tests/goToPageScript.js index 2b2cf33b..bccbc5d2 100644 --- a/maps/tests/goToPageScript.js +++ b/maps/tests/goToPageScript.js @@ -1,14 +1,16 @@ +/// var zoneName = "popUpGoToPageZone"; var urlPricing = "https://workadventu.re/pricing"; var urlGettingStarted = "https://workadventu.re/getting-started"; -var isCoWebSiteOpened = false; +var urlRelativeMap = "script_api.json"; +var isCoWebSiteOpened = false; WA.onChatMessage((message => { - WA.sendChatMessage('Poly Parrot says: "'+message+'"', 'Poly Parrot'); + WA.sendChatMessage('Poly Parrot says: "' + message + '"', 'Poly Parrot'); })); WA.onEnterZone(zoneName, () => { - WA.openPopup("popUp","Open Links",[ + WA.openPopup("popUp", "Open Links", [ { label: "Open Tab", className: "popUpElement", @@ -18,27 +20,34 @@ WA.onEnterZone(zoneName, () => { }) }, { - label: "Go To Page", className : "popUpElement", - callback:(popup => { + label: "Go To Page", className: "popUpElement", + callback: (popup => { WA.goToPage(urlPricing); popup.close(); }) - } - , + }, { - label: "openCoWebSite", className : "popUpElement", - callback:(popup => { + label: "openCoWebSite", className: "popUpElement", + callback: (popup => { WA.openCoWebSite(urlPricing); isCoWebSiteOpened = true; popup.close(); }) + }, { + label: "load grouped map", + className: "popUpElement", + callback: (popup => { + WA.goToRoom(urlRelativeMap); + popup.close(); + }) + }]); }) WA.onLeaveZone(zoneName, () => { - if (isCoWebSiteOpened) { + if(isCoWebSiteOpened) { WA.closeCoWebSite(); isCoWebSiteOpened = false; } diff --git a/maps/tests/index.html b/maps/tests/index.html index 9c95c281..af70151e 100644 --- a/maps/tests/index.html +++ b/maps/tests/index.html @@ -41,6 +41,14 @@ Testing scripting API with a script + + + + Success Failure Pending + + + Testing scripting API with a script +