Merge branch 'develop' of github.com:thecodingmachine/workadventure into main

This commit is contained in:
_Bastler 2021-06-16 19:58:34 +02:00
commit b96ba7f8c5
9 changed files with 95 additions and 46 deletions

View File

@ -187,6 +187,26 @@ Example:
WA.goToPage('https://www.wikipedia.org/'); 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/<path to global map>.json#start-layer-2")
```
### Opening/closing a web page in an iFrame ### Opening/closing a web page in an iFrame
``` ```

View File

@ -1,11 +0,0 @@
import * as tg from "generic-type-guard";
export const isExitUrlEvent =
new tg.IsInterface().withProperties({
url: tg.isString,
}).get();
/**
* A message sent from the iFrame to the game to trigger Exit Url
*/
export type ExitUrlEvent = tg.GuardedType<typeof isExitUrlEvent>;

View File

@ -5,12 +5,12 @@ import type { ChatEvent } from './ChatEvent';
import type { ClosePopupEvent } from './ClosePopupEvent'; import type { ClosePopupEvent } from './ClosePopupEvent';
import type { EnterLeaveEvent } from './EnterLeaveEvent'; import type { EnterLeaveEvent } from './EnterLeaveEvent';
import type { GoToPageEvent } from './GoToPageEvent'; import type { GoToPageEvent } from './GoToPageEvent';
import type { LoadPageEvent } from './LoadPageEvent';
import type { OpenCoWebSiteEvent } from './OpenCoWebSiteEvent'; import type { OpenCoWebSiteEvent } from './OpenCoWebSiteEvent';
import type { OpenPopupEvent } from './OpenPopupEvent'; import type { OpenPopupEvent } from './OpenPopupEvent';
import type { OpenTabEvent } from './OpenTabEvent'; import type { OpenTabEvent } from './OpenTabEvent';
import type { UserInputChatEvent } from './UserInputChatEvent'; import type { UserInputChatEvent } from './UserInputChatEvent';
import type { ExitUrlEvent } from './ExitUrlEvent'; import type { LoadSoundEvent} from "./LoadSoundEvent";
import type {LoadSoundEvent} from "./LoadSoundEvent";
import type {PlaySoundEvent} from "./PlaySoundEvent"; import type {PlaySoundEvent} from "./PlaySoundEvent";
@ -21,6 +21,7 @@ export interface TypedMessageEvent<T> extends MessageEvent {
export type IframeEventMap = { export type IframeEventMap = {
//getState: GameStateEvent, //getState: GameStateEvent,
// updateTile: UpdateTileEvent // updateTile: UpdateTileEvent
loadPage: LoadPageEvent
chat: ChatEvent, chat: ChatEvent,
openPopup: OpenPopupEvent openPopup: OpenPopupEvent
closePopup: ClosePopupEvent closePopup: ClosePopupEvent
@ -32,7 +33,6 @@ export type IframeEventMap = {
restorePlayerControls: null restorePlayerControls: null
displayBubble: null displayBubble: null
removeBubble: null removeBubble: null
exitUrl : ExitUrlEvent
closeChatMessage : null closeChatMessage : null
loadSound: LoadSoundEvent loadSound: LoadSoundEvent
playSound: PlaySoundEvent playSound: PlaySoundEvent

View File

@ -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<typeof isLoadPageEvent>;

View File

@ -12,7 +12,7 @@ import { GoToPageEvent, isGoToPageEvent } from "./Events/GoToPageEvent";
import { isOpenCoWebsite, OpenCoWebSiteEvent } from "./Events/OpenCoWebSiteEvent"; import { isOpenCoWebsite, OpenCoWebSiteEvent } from "./Events/OpenCoWebSiteEvent";
import { IframeEventMap, IframeEvent, IframeResponseEvent, IframeResponseEventMap, isIframeEventWrapper, TypedMessageEvent } from "./Events/IframeEvent"; import { IframeEventMap, IframeEvent, IframeResponseEvent, IframeResponseEventMap, isIframeEventWrapper, TypedMessageEvent } from "./Events/IframeEvent";
import type { UserInputChatEvent } from "./Events/UserInputChatEvent"; import type { UserInputChatEvent } from "./Events/UserInputChatEvent";
import { isExitUrlEvent } from './Events/ExitUrlEvent'; import { isLoadPageEvent } from './Events/LoadPageEvent';
import {isPlaySoundEvent, PlaySoundEvent} from "./Events/PlaySoundEvent"; import {isPlaySoundEvent, PlaySoundEvent} from "./Events/PlaySoundEvent";
import {isStopSoundEvent, StopSoundEvent} from "./Events/StopSoundEvent"; import {isStopSoundEvent, StopSoundEvent} from "./Events/StopSoundEvent";
import {isLoadSoundEvent, LoadSoundEvent} from "./Events/LoadSoundEvent"; import {isLoadSoundEvent, LoadSoundEvent} from "./Events/LoadSoundEvent";
@ -33,6 +33,10 @@ class IframeListener {
private readonly _goToPageStream: Subject<GoToPageEvent> = new Subject(); private readonly _goToPageStream: Subject<GoToPageEvent> = new Subject();
public readonly goToPageStream = this._goToPageStream.asObservable(); public readonly goToPageStream = this._goToPageStream.asObservable();
private readonly _loadPageStream: Subject<string> = new Subject();
public readonly loadPageStream = this._loadPageStream.asObservable();
private readonly _openCoWebSiteStream: Subject<OpenCoWebSiteEvent> = new Subject(); private readonly _openCoWebSiteStream: Subject<OpenCoWebSiteEvent> = new Subject();
public readonly openCoWebSiteStream = this._openCoWebSiteStream.asObservable(); public readonly openCoWebSiteStream = this._openCoWebSiteStream.asObservable();
@ -140,9 +144,8 @@ class IframeListener {
} }
else if (payload.type === 'removeBubble') { else if (payload.type === 'removeBubble') {
this._removeBubbleStream.next(); this._removeBubbleStream.next();
} }else if (payload.type === 'loadPage' && isLoadPageEvent(payload.data)){
else if (payload.type === 'exitUrl' && isExitUrlEvent(payload.data)){ this._loadPageStream.next(payload.data.url);
this._exitUrlStream.next(payload.data.url);
} }
} }

View File

@ -80,7 +80,7 @@ import CanvasTexture = Phaser.Textures.CanvasTexture;
import GameObject = Phaser.GameObjects.GameObject; import GameObject = Phaser.GameObjects.GameObject;
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR; import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
import DOMElement = Phaser.GameObjects.DOMElement; import DOMElement = Phaser.GameObjects.DOMElement;
import EVENT_TYPE =Phaser.Scenes.Events; import EVENT_TYPE =Phaser.Scenes.Events
import type {Subscription} from "rxjs"; import type {Subscription} from "rxjs";
import {worldFullMessageStream} from "../../Connexion/WorldFullMessageStream"; import {worldFullMessageStream} from "../../Connexion/WorldFullMessageStream";
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager"; import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
@ -930,7 +930,13 @@ export class GameScene extends DirtyScene implements CenterListener {
this.iframeSubscriptionList.push(iframeListener.enablePlayerControlStream.subscribe(()=>{ this.iframeSubscriptionList.push(iframeListener.enablePlayerControlStream.subscribe(()=>{
this.userInputManager.restoreControls(); 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; let scriptedBubbleSprite : Sprite;
this.iframeSubscriptionList.push(iframeListener.displayBubbleStream.subscribe(()=>{ this.iframeSubscriptionList.push(iframeListener.displayBubbleStream.subscribe(()=>{
scriptedBubbleSprite = new Sprite(this,this.CurrentPlayer.x + 25,this.CurrentPlayer.y,'circleSprite-white'); scriptedBubbleSprite = new Sprite(this,this.CurrentPlayer.x + 25,this.CurrentPlayer.y,'circleSprite-white');
@ -1134,10 +1140,10 @@ export class GameScene extends DirtyScene implements CenterListener {
} }
//todo: push that into the gameManager //todo: push that into the gameManager
private loadNextGame(exitSceneIdentifier: string): void { private loadNextGame(exitSceneIdentifier: string): Promise<void> {
const {roomId, hash} = Room.getIdFromIdentifier(exitSceneIdentifier, this.MapUrlFile, this.instance); const {roomId, hash} = Room.getIdFromIdentifier(exitSceneIdentifier, this.MapUrlFile, this.instance);
const room = new Room(roomId); const room = new Room(roomId);
gameManager.loadMap(room, this.scene).catch(() => {}); return gameManager.loadMap(room, this.scene).catch(() => {});
} }
private startUser(layer: ITiledMapTileLayer): PositionInterface { private startUser(layer: ITiledMapTileLayer): PositionInterface {

View File

@ -9,11 +9,11 @@ import type { ClosePopupEvent } from "./Api/Events/ClosePopupEvent";
import type { OpenTabEvent } from "./Api/Events/OpenTabEvent"; import type { OpenTabEvent } from "./Api/Events/OpenTabEvent";
import type { GoToPageEvent } from "./Api/Events/GoToPageEvent"; import type { GoToPageEvent } from "./Api/Events/GoToPageEvent";
import type { OpenCoWebSiteEvent } from "./Api/Events/OpenCoWebSiteEvent"; import type { OpenCoWebSiteEvent } from "./Api/Events/OpenCoWebSiteEvent";
import {ExitUrlEvent} from "./Api/Events/ExitUrlEvent"; import type { PlaySoundEvent } from "./Api/Events/PlaySoundEvent";
import type {PlaySoundEvent} from "./Api/Events/PlaySoundEvent"; import type { StopSoundEvent } from "./Api/Events/StopSoundEvent";
import type {StopSoundEvent} from "./Api/Events/StopSoundEvent"; import type { LoadSoundEvent } from "./Api/Events/LoadSoundEvent";
import type {LoadSoundEvent} from "./Api/Events/LoadSoundEvent";
import SoundConfig = Phaser.Types.Sound.SoundConfig; import SoundConfig = Phaser.Types.Sound.SoundConfig;
import type { LoadPageEvent } from './Api/Events/LoadPageEvent';
interface WorkAdventureApi { interface WorkAdventureApi {
sendChatMessage(message: string, author: string): void; sendChatMessage(message: string, author: string): void;
@ -21,16 +21,16 @@ interface WorkAdventureApi {
closeChatMessage(): void; closeChatMessage(): void;
onEnterZone(name: string, callback: () => void): void; onEnterZone(name: string, callback: () => void): void;
onLeaveZone(name: string, callback: () => void): void; onLeaveZone(name: string, callback: () => void): void;
openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[], input: boolean): Popup; openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup;
openTab(url: string): void; openTab(url: string): void;
goToPage(url: string): void; goToPage(url: string): void;
goToRoom(url: string): void;
openCoWebSite(url: string): void; openCoWebSite(url: string): void;
closeCoWebSite(): void; closeCoWebSite(): void;
disablePlayerControls(): void; disablePlayerControls(): void;
restorePlayerControls(): void; restorePlayerControls(): void;
displayBubble(): void; displayBubble(): void;
removeBubble(): void; removeBubble(): void;
exitUrl(url : string) : void;
loadSound(url : string): Sound; loadSound(url : string): Sound;
} }
@ -178,6 +178,15 @@ window.WA = {
}, '*'); }, '*');
}, },
goToRoom(url: string): void {
window.parent.postMessage({
"type" : 'loadPage',
"data" : {
url
} as LoadPageEvent
},'*');
},
openCoWebSite(url : string) : void{ openCoWebSite(url : string) : void{
window.parent.postMessage({ window.parent.postMessage({
"type" : 'openCoWebSite', "type" : 'openCoWebSite',
@ -256,14 +265,6 @@ window.WA = {
} }
subject.subscribe(callback); subject.subscribe(callback);
}, },
exitUrl(url : string) : void{
window.parent.postMessage({
"type" : 'exitUrl',
"data" : {
url
} as ExitUrlEvent
},'*');
},
} }
window.addEventListener('message', message => { window.addEventListener('message', message => {

View File

@ -1,14 +1,16 @@
/// <reference path="../../front/src/iframe_api.ts" />
var zoneName = "popUpGoToPageZone"; var zoneName = "popUpGoToPageZone";
var urlPricing = "https://workadventu.re/pricing"; var urlPricing = "https://workadventu.re/pricing";
var urlGettingStarted = "https://workadventu.re/getting-started"; var urlGettingStarted = "https://workadventu.re/getting-started";
var isCoWebSiteOpened = false; var urlRelativeMap = "script_api.json";
var isCoWebSiteOpened = false;
WA.onChatMessage((message => { WA.onChatMessage((message => {
WA.sendChatMessage('Poly Parrot says: "'+message+'"', 'Poly Parrot'); WA.sendChatMessage('Poly Parrot says: "' + message + '"', 'Poly Parrot');
})); }));
WA.onEnterZone(zoneName, () => { WA.onEnterZone(zoneName, () => {
WA.openPopup("popUp","Open Links",[ WA.openPopup("popUp", "Open Links", [
{ {
label: "Open Tab", label: "Open Tab",
className: "popUpElement", className: "popUpElement",
@ -18,27 +20,34 @@ WA.onEnterZone(zoneName, () => {
}) })
}, },
{ {
label: "Go To Page", className : "popUpElement", label: "Go To Page", className: "popUpElement",
callback:(popup => { callback: (popup => {
WA.goToPage(urlPricing); WA.goToPage(urlPricing);
popup.close(); popup.close();
}) })
} },
,
{ {
label: "openCoWebSite", className : "popUpElement", label: "openCoWebSite", className: "popUpElement",
callback:(popup => { callback: (popup => {
WA.openCoWebSite(urlPricing); WA.openCoWebSite(urlPricing);
isCoWebSiteOpened = true; isCoWebSiteOpened = true;
popup.close(); popup.close();
}) })
}, {
label: "load grouped map",
className: "popUpElement",
callback: (popup => {
WA.goToRoom(urlRelativeMap);
popup.close();
})
}]); }]);
}) })
WA.onLeaveZone(zoneName, () => { WA.onLeaveZone(zoneName, () => {
if (isCoWebSiteOpened) { if(isCoWebSiteOpened) {
WA.closeCoWebSite(); WA.closeCoWebSite();
isCoWebSiteOpened = false; isCoWebSiteOpened = false;
} }

View File

@ -41,6 +41,14 @@
<td> <td>
<a href="#" class="testLink" data-testmap="script_api.json" target="_blank">Testing scripting API with a script</a> <a href="#" class="testLink" data-testmap="script_api.json" target="_blank">Testing scripting API with a script</a>
</td> </td>
</tr>
<tr>
<td>
<input type="radio" name="test-scripting-api"> Success <input type="radio" name="test-scripting-api"> Failure <input type="radio" name="test-scripting-api" checked> Pending
</td>
<td>
<a href="#" class="testLink" data-testmap="goToPage.json" target="_blank">Testing scripting API with a script</a>
</td>
</tr> </tr>
<tr> <tr>
<td> <td>