game state can be read out by the client APIs
# Conflicts: # front/src/Api/IframeListener.ts # front/src/Phaser/Game/GameScene.ts # front/src/iframe_api.ts
This commit is contained in:
parent
5dc2f0ac47
commit
3836d5037c
11
front/src/Api/Events/ApiGameStateEvent.ts
Normal file
11
front/src/Api/Events/ApiGameStateEvent.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import * as tg from "generic-type-guard";
|
||||
|
||||
export const isGameStateEvent =
|
||||
new tg.IsInterface().withProperties({
|
||||
roomId: tg.isString,
|
||||
data:tg.isObject
|
||||
}).get();
|
||||
/**
|
||||
* A message sent from the game to the iFrame when a user enters or leaves a zone marked with the "zone" property.
|
||||
*/
|
||||
export type GameStateEvent = tg.GuardedType<typeof isGameStateEvent>;
|
@ -12,6 +12,8 @@ import {ClosePopupEvent, isClosePopupEvent} from "./Events/ClosePopupEvent";
|
||||
import {scriptUtils} from "./ScriptUtils";
|
||||
import {GoToPageEvent, isGoToPageEvent} from "./Events/GoToPageEvent";
|
||||
import {isOpenCoWebsite, OpenCoWebSiteEvent} from "./Events/OpenCoWebSiteEvent";
|
||||
import { GameStateEvent } from './Events/ApiGameStateEvent';
|
||||
import { deepFreezeClone as deepFreezeClone } from '../utility';
|
||||
|
||||
|
||||
/**
|
||||
@ -52,6 +54,10 @@ class IframeListener {
|
||||
private readonly _removeBubbleStream: Subject<void> = new Subject();
|
||||
public readonly removeBubbleStream = this._removeBubbleStream.asObservable();
|
||||
|
||||
|
||||
private readonly _gameStateStream: Subject<void> = new Subject();
|
||||
public readonly gameStateStream = this._gameStateStream.asObservable();
|
||||
|
||||
private readonly iframes = new Set<HTMLIFrameElement>();
|
||||
private readonly scripts = new Map<string, HTMLIFrameElement>();
|
||||
|
||||
@ -103,6 +109,8 @@ class IframeListener {
|
||||
}
|
||||
else if (payload.type === 'removeBubble'){
|
||||
this._removeBubbleStream.next();
|
||||
}else if(payload.type=="getState"){
|
||||
this._gameStateStream.next();
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,6 +119,14 @@ class IframeListener {
|
||||
|
||||
}
|
||||
|
||||
|
||||
sendFrozenGameStateEvent(gameStateEvent: GameStateEvent) {
|
||||
this.postMessage({
|
||||
'type': 'gameState',
|
||||
'data': deepFreezeClone(gameStateEvent)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the passed iFrame to send/receive messages via the API.
|
||||
*/
|
||||
|
@ -841,6 +841,13 @@ ${escapedMessage}
|
||||
this.iframeSubscriptionList.push(iframeListener.enablePlayerControlStream.subscribe(()=>{
|
||||
this.userInputManager.restoreControls();
|
||||
}));
|
||||
this.iframeSubscriptionList.push(iframeListener.gameStateStream.subscribe(()=>{
|
||||
iframeListener.sendFrozenGameStateEvent({
|
||||
roomId:this.RoomId,
|
||||
data: this.mapFile
|
||||
})
|
||||
}));
|
||||
|
||||
let scriptedBubbleSprite : Sprite;
|
||||
this.iframeSubscriptionList.push(iframeListener.displayBubbleStream.subscribe(()=>{
|
||||
scriptedBubbleSprite = new Sprite(this,this.CurrentPlayer.x + 25,this.CurrentPlayer.y,'circleSprite-white');
|
||||
|
@ -9,6 +9,7 @@ import {ClosePopupEvent} from "./Api/Events/ClosePopupEvent";
|
||||
import {OpenTabEvent} from "./Api/Events/OpenTabEvent";
|
||||
import {GoToPageEvent} from "./Api/Events/GoToPageEvent";
|
||||
import {OpenCoWebSiteEvent} from "./Api/Events/OpenCoWebSiteEvent";
|
||||
import { GameStateEvent, isGameStateEvent } from './Api/Events/ApiGameStateEvent';
|
||||
|
||||
interface WorkAdventureApi {
|
||||
sendChatMessage(message: string, author: string): void;
|
||||
@ -24,6 +25,7 @@ interface WorkAdventureApi {
|
||||
restorePlayerControl() : void;
|
||||
displayBubble() : void;
|
||||
removeBubble() : void;
|
||||
getGameState():Promise<unknown>
|
||||
}
|
||||
|
||||
declare global {
|
||||
@ -74,7 +76,23 @@ class Popup {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const stateResolvers:Array<(event:GameStateEvent)=>void> =[]
|
||||
|
||||
window.WA = {
|
||||
|
||||
|
||||
|
||||
getGameState(){
|
||||
return new Promise<GameStateEvent>((resolver,thrower)=>{
|
||||
stateResolvers.push(resolver);
|
||||
window.parent.postMessage({
|
||||
type:"getState"
|
||||
},"*")
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Send a message in the chat.
|
||||
* Only the local user will receive this message.
|
||||
@ -224,6 +242,10 @@ window.addEventListener('message', message => {
|
||||
if (callback) {
|
||||
callback(popup);
|
||||
}
|
||||
}else if(payload.type=="gameState" && isGameStateEvent(payloadData)){
|
||||
stateResolvers.forEach(resolver=>{
|
||||
resolver(payloadData);
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
18
front/src/utility.ts
Normal file
18
front/src/utility.ts
Normal file
@ -0,0 +1,18 @@
|
||||
export function deepFreezeClone<T> (obj:T):Readonly<T> {
|
||||
return deepFreeze(JSON.parse(JSON.stringify(obj)));
|
||||
}
|
||||
|
||||
function deepFreeze<T> (obj:T):T{
|
||||
Object.freeze(obj);
|
||||
if (obj === undefined) {
|
||||
return obj;
|
||||
}
|
||||
const propertyNames = Object.getOwnPropertyNames(obj) as Array<keyof T>;
|
||||
propertyNames.forEach(function (prop) {
|
||||
if (obj[prop] !== null&& (typeof obj[prop] === "object" || typeof obj[prop] === "function") && !Object.isFrozen(obj[prop])) {
|
||||
deepFreezeClone(obj[prop]);
|
||||
}
|
||||
});
|
||||
|
||||
return obj;
|
||||
}
|
Loading…
Reference in New Issue
Block a user