correction of adding custom menu

correction of setProperty
updating CHANGELOG
updating api-reference
This commit is contained in:
GRL 2021-05-28 12:13:10 +02:00
parent 5565ddd3f4
commit 858a513569
9 changed files with 87 additions and 42 deletions

View file

@ -19,6 +19,13 @@
- Improved virtual joystick size (adapts to the zoom level)
- New scripting API features:
- Use `WA.loadSound(): Sound` to load / play / stop a sound
- Use `WA.showLayer(): void` to show a layer
- Use `WA.hideLayer(): void` to hide a layer
- Use `WA.setProperty() : void` to add or change existing property of a layer
- Use `WA.onPlayerMove(): void` to track the movement of the current player
- Use `WA.getCurrentUser(): Promise<User>` to get the ID, name and tags of the current player
- Use `WA.getCurrentRoom(): Promise<Room>` to get the ID, JSON map file, url of the map of the current room and the layer where the current player started
- Use `WA.registerMenuCommand(): void` to add a custom menu
### Bug Fixes

View file

@ -323,7 +323,7 @@ WA.getCurrentRoom((room) => {
### Add a custom menu
```
registerMenuCommand(commandDescriptor: string, callback: (commandDescriptor: string) => void)
registerMenuCommand(commandDescriptor: string, callback: (commandDescriptor: string) => void): void
```
Add a custom menu item containing the text `commandDescriptor`. A click on the menu will trigger the `callback`.

View file

@ -15,8 +15,8 @@ import type { UserInputChatEvent } from './UserInputChatEvent';
import type { DataLayerEvent } from "./DataLayerEvent";
import type { LayerEvent } from './LayerEvent';
import type { SetPropertyEvent } from "./setPropertyEvent";
import type {LoadSoundEvent} from "./LoadSoundEvent";
import type {PlaySoundEvent} from "./PlaySoundEvent";
import type { LoadSoundEvent } from "./LoadSoundEvent";
import type { PlaySoundEvent } from "./PlaySoundEvent";
export interface TypedMessageEvent<T> extends MessageEvent {
@ -42,7 +42,6 @@ export type IframeEventMap = {
hideLayer: LayerEvent
setProperty: SetPropertyEvent
getDataLayer: undefined
//tilsetEvent: TilesetEvent
loadSound: LoadSoundEvent
playSound: PlaySoundEvent
stopSound: null

View file

@ -20,7 +20,6 @@ import { Math } from 'phaser';
import type { DataLayerEvent } from "./Events/DataLayerEvent";
import { isMenuItemRegisterEvent } from './Events/MenuItemRegisterEvent';
import type { MenuItemClickedEvent } from './Events/MenuItemClickedEvent';
//import { isTilesetEvent, TilesetEvent } from "./Events/TilesetEvent";
import { isPlaySoundEvent, PlaySoundEvent } from "./Events/PlaySoundEvent";
import { isStopSoundEvent, StopSoundEvent } from "./Events/StopSoundEvent";
import { isLoadSoundEvent, LoadSoundEvent } from "./Events/LoadSoundEvent";
@ -81,8 +80,8 @@ class IframeListener {
private readonly _registerMenuCommandStream: Subject<string> = new Subject();
public readonly registerMenuCommandStream = this._registerMenuCommandStream.asObservable();
/* private readonly _tilesetLoaderStream: Subject<TilesetEvent> = new Subject();
public readonly tilesetLoaderStream = this._tilesetLoaderStream.asObservable();*/
private readonly _unregisterMenuCommandStream: Subject<string> = new Subject();
public readonly unregisterMenuCommandStream = this._unregisterMenuCommandStream.asObservable();
private readonly _playSoundStream: Subject<PlaySoundEvent> = new Subject();
public readonly playSoundStream = this._playSoundStream.asObservable();
@ -94,6 +93,7 @@ class IframeListener {
public readonly loadSoundStream = this._loadSoundStream.asObservable();
private readonly iframes = new Set<HTMLIFrameElement>();
private readonly iframeCloseCallbacks = new Map<HTMLIFrameElement, (() => void)[]>();
private readonly scripts = new Map<string, HTMLIFrameElement>();
private sendPlayerMove: boolean = false;
@ -103,7 +103,8 @@ class IframeListener {
// Let's only accept messages from the iframe that are allowed.
// Note: maybe we could restrict on the domain too for additional security (in case the iframe goes to another domain).
let foundSrc: string | null = null;
for (const iframe of this.iframes) {
let iframe: HTMLIFrameElement;
for (iframe of this.iframes) {
if (iframe.contentWindow === message.source) {
foundSrc = iframe.src;
break;
@ -171,9 +172,12 @@ class IframeListener {
} else if (payload.type == "getDataLayer") {
this._dataLayerChangeStream.next();
} else if (payload.type == "registerMenuCommand" && isMenuItemRegisterEvent(payload.data)) {
const data = payload.data.menutItem;
// @ts-ignore
this.iframeCloseCallbacks.get(iframe).push(() => {
this._unregisterMenuCommandStream.next(data);
})
this._registerMenuCommandStream.next(payload.data.menutItem)
/* } else if (payload.type == "tilsetEvent" && isTilesetEvent(payload.data)) {
this._tilesetLoaderStream.next(payload.data);*/
}
}
}, false);
@ -200,9 +204,13 @@ class IframeListener {
*/
registerIframe(iframe: HTMLIFrameElement): void {
this.iframes.add(iframe);
this.iframeCloseCallbacks.set(iframe, []);
}
unregisterIframe(iframe: HTMLIFrameElement): void {
this.iframeCloseCallbacks.get(iframe)?.forEach(callback => {
callback();
});
this.iframes.delete(iframe);
}

View file

@ -1,7 +1,7 @@
import type {ITiledMap, ITiledMapLayer, ITiledMapTileLayer} from "../Map/ITiledMap";
import type { ITiledMap, ITiledMapLayer } from "../Map/ITiledMap";
import { flattenGroupLayersMap } from "../Map/LayersFlattener";
import TilemapLayer = Phaser.Tilemaps.TilemapLayer;
import {DEPTH_OVERLAY_INDEX} from "./DepthIndexes";
import { DEPTH_OVERLAY_INDEX } from "./DepthIndexes";
export type PropertyChangeCallback = (newValue: string | number | boolean | undefined, oldValue: string | number | boolean | undefined, allProps: Map<string, string | boolean | number>) => void;
@ -118,11 +118,11 @@ export class GameMap {
}
public findLayer(layerName: string): ITiledMapLayer | undefined {
return this.flatLayers.find((layer) => layer.name = layerName);
return this.flatLayers.find((layer) => layer.name === layerName);
}
public findPhaserLayer(layerName: string): TilemapLayer | undefined {
return this.phaserLayers.find((layer) => layer.layer.name = layerName);
return this.phaserLayers.find((layer) => layer.layer.name === layerName);
}
public addTerrain(terrain : Phaser.Tilemaps.Tileset): void {

View file

@ -927,13 +927,6 @@ ${escapedMessage}
})
}));
/* this.iframeSubscriptionList.push(iframeListener.tilesetLoaderStream.subscribe((tileset) => {
//this.load.tilemapTiledJSON('logo', tileset.imgUrl);
this.load.image('logo', tileset.imgUrl);
this.Terrains.push(this.Map.addTilesetImage(tileset.name, tileset.imgUrl, tileset.tilewidth, tileset.tileheight, tileset.margin, tileset.spacing));
this.gameMap.addTerrain(this.Terrains[this.Terrains.length - 1]);
}))*/
}
private setPropertyLayer(layerName: string, propertyName: string, propertyValue: string | number | boolean | undefined): void {

View file

@ -49,7 +49,10 @@ export class MenuScene extends Phaser.Scene {
this.subscriptions.add(iframeListener.registerMenuCommandStream.subscribe(menuCommand => {
this.addMenuOption(menuCommand);
}))
this.subscriptions.add(iframeListener.unregisterMenuCommandStream.subscribe(menuCommand => {
this.destroyMenu(menuCommand);
}))
}
@ -386,6 +389,10 @@ export class MenuScene extends Phaser.Scene {
}
}
public destroyMenu(menu: string) {
this.menuElement.getChildByID(menu).remove();
}
public isDirty(): boolean {
return false;
}

View file

@ -17,9 +17,9 @@ import { DataLayerEvent, isDataLayerEvent } from "./Api/Events/DataLayerEvent";
import type { ITiledMap } from "./Phaser/Map/ITiledMap";
import type { MenuItemRegisterEvent } from "./Api/Events/MenuItemRegisterEvent";
import { isMenuItemClickedEvent } from "./Api/Events/MenuItemClickedEvent";
import type {PlaySoundEvent} from "./Api/Events/PlaySoundEvent";
import type {StopSoundEvent} from "./Api/Events/StopSoundEvent";
import type {LoadSoundEvent} from "./Api/Events/LoadSoundEvent";
import type { PlaySoundEvent } from "./Api/Events/PlaySoundEvent";
import type { StopSoundEvent } from "./Api/Events/StopSoundEvent";
import type { LoadSoundEvent } from "./Api/Events/LoadSoundEvent";
import SoundConfig = Phaser.Types.Sound.SoundConfig;
interface WorkAdventureApi {
@ -47,8 +47,6 @@ interface WorkAdventureApi {
registerMenuCommand(commandDescriptor: string, callback: (commandDescriptor: string) => void): void
getCurrentUser(): Promise<User>
getCurrentRoom(): Promise<Room>
//loadTileset(name: string, imgUrl : string, tilewidth : number, tileheight : number, margin : number, spacing : number): void;
onPlayerMove(callback: (playerMovedEvent: HasPlayerMovedEvent) => void): void
}
@ -176,7 +174,6 @@ const gameStateResolver: Array<(event: GameStateEvent) => void> = []
const dataLayerResolver: Array<(event: DataLayerEvent) => void> = []
let immutableData: GameStateEvent;
//const callbackPlayerMoved: { [type: string]: HasPlayerMovedEventCallback | ((arg?: HasPlayerMovedEvent | never) => void) } = {}
const callbackPlayerMoved: Array<(event: HasPlayerMovedEvent) => void> = []
function postToParent(content: IframeEvent<keyof IframeEventMap>) {
@ -193,20 +190,6 @@ window.WA = {
})
},
/* loadTileset(name: string, imgUrl : string, tilewidth : number, tileheight : number, margin : number, spacing : number): void {
postToParent({
type: "tilsetEvent",
data: {
name: name,
imgUrl: imgUrl,
tilewidth: tilewidth,
tileheight: tileheight,
margin: margin,
spacing: spacing
} as TilesetEvent
})
},*/
getCurrentUser(): Promise<User> {
return getGameState().then((gameState) => {
return {id: gameState.uuid, nickName: gameState.nickname, tags: gameState.tags};
@ -353,7 +336,7 @@ window.WA = {
return popup;
},
registerMenuCommand(commandDescriptor: string, callback: (commandDescriptor: string) => void) {
registerMenuCommand(commandDescriptor: string, callback: (commandDescriptor: string) => void): void {
menuCallbacks.set(commandDescriptor, callback);
window.parent.postMessage({
'type': 'registerMenuCommand',

View file

@ -82,6 +82,54 @@
<a href="#" class="testLink" data-testmap="energy.json" target="_blank">Test energy consumption</a>
</td>
</tr>
<tr>
<td>
<input type="radio" name="test-custom-menu"> Success <input type="radio" name="test-custom-menu"> Failure <input type="radio" name="test-custom-menu" checked> Pending
</td>
<td>
<a href="#" class="testLink" data-testmap="Metadata/customMenu.json" target="_blank">Testing add a custom menu by scripting API</a>
</td>
</tr>
<tr>
<td>
<input type="radio" name="test-getCurrentRoom"> Success <input type="radio" name="test-getCurrentRoom"> Failure <input type="radio" name="test-getCurrentRoom" checked> Pending
</td>
<td>
<a href="#" class="testLink" data-testmap="Metadata/getCurrentRoom.json" target="_blank">Testing return current room attributes by Scripting API (Need to test from current user)</a>
</td>
</tr>
<tr>
<td>
<input type="radio" name="test-getCurrentUser"> Success <input type="radio" name="test-getCurrentUser"> Failure <input type="radio" name="test-getCurrentUser" checked> Pending
</td>
<td>
<a href="#" class="testLink" data-testmap="Metadata/getCurrentUser.json" target="_blank">Testing return current user attributes by Scripting API</a>
</td>
</tr>
<tr>
<td>
<input type="radio" name="test-player-move"> Success <input type="radio" name="test-player-move"> Failure <input type="radio" name="test-player-move" checked> Pending
</td>
<td>
<a href="#" class="testLink" data-testmap="Metadata/playerMove.json" target="_blank">Test listening player movement by Scripting API</a>
</td>
</tr>
<tr>
<td>
<input type="radio" name="test-setProperty"> Success <input type="radio" name="test-setProperty"> Failure <input type="radio" name="test-setProperty" checked> Pending
</td>
<td>
<a href="#" class="testLink" data-testmap="Metadata/setProperty.json" target="_blank">Testing set a property on a layer by Scripting API</a>
</td>
</tr>
<tr>
<td>
<input type="radio" name="test-show-hide"> Success <input type="radio" name="test-show-hide"> Failure <input type="radio" name="test-show-hide" checked> Pending
</td>
<td>
<a href="#" class="testLink" data-testmap="Metadata/showHideLayer.json" target="_blank">Testing show or hide a layer by Scripting API</a>
</td>
</tr>
</table>
<script>