From d51ac45079ef40f5304a63b8186596692c3d6feb Mon Sep 17 00:00:00 2001 From: GRL Date: Wed, 7 Jul 2021 14:26:53 +0200 Subject: [PATCH 1/7] Show/Hide Layer now unset collision and can show/hide all the layer in a group layer --- front/src/Api/Events/LayerEvent.ts | 1 + front/src/Api/iframe/room.ts | 10 ++++---- front/src/Phaser/Game/GameMap.ts | 4 +++ front/src/Phaser/Game/GameScene.ts | 39 +++++++++++++++++++++--------- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/front/src/Api/Events/LayerEvent.ts b/front/src/Api/Events/LayerEvent.ts index b56c3163..d3fdda22 100644 --- a/front/src/Api/Events/LayerEvent.ts +++ b/front/src/Api/Events/LayerEvent.ts @@ -3,6 +3,7 @@ import * as tg from "generic-type-guard"; export const isLayerEvent = new tg.IsInterface() .withProperties({ name: tg.isString, + group: tg.isBoolean, }) .get(); /** diff --git a/front/src/Api/iframe/room.ts b/front/src/Api/iframe/room.ts index c70d0aad..8ff31375 100644 --- a/front/src/Api/iframe/room.ts +++ b/front/src/Api/iframe/room.ts @@ -4,7 +4,7 @@ import { isDataLayerEvent } from "../Events/DataLayerEvent"; import { EnterLeaveEvent, isEnterLeaveEvent } from "../Events/EnterLeaveEvent"; import { isGameStateEvent } from "../Events/GameStateEvent"; -import {IframeApiContribution, queryWorkadventure, sendToWorkadventure} from "./IframeApiContribution"; +import { IframeApiContribution, queryWorkadventure, sendToWorkadventure } from "./IframeApiContribution"; import { apiCallback } from "./registeredCallbacks"; import type { ITiledMap } from "../../Phaser/Map/ITiledMap"; @@ -93,11 +93,11 @@ export class WorkadventureRoomCommands extends IframeApiContribution layer.layer.name === layerName); } + public findPhaserLayers(groupName: string): TilemapLayer[] { + return this.phaserLayers.filter((l) => l.layer.name.includes(groupName)); + } + public addTerrain(terrain: Phaser.Tilemaps.Tileset): void { for (const phaserLayer of this.phaserLayers) { phaserLayer.tileset.push(terrain); diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index d767f0f4..5c3edfac 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -1022,13 +1022,13 @@ ${escapedMessage} this.iframeSubscriptionList.push( iframeListener.showLayerStream.subscribe((layerEvent) => { - this.setLayerVisibility(layerEvent.name, true); + this.setLayerVisibility(layerEvent.name, true, layerEvent.group); }) ); this.iframeSubscriptionList.push( iframeListener.hideLayerStream.subscribe((layerEvent) => { - this.setLayerVisibility(layerEvent.name, false); + this.setLayerVisibility(layerEvent.name, false, layerEvent.group); }) ); @@ -1044,7 +1044,7 @@ ${escapedMessage} }) ); - iframeListener.registerAnswerer('getState', () => { + iframeListener.registerAnswerer("getState", () => { return { mapUrl: this.MapUrlFile, startLayerName: this.startPositionCalculator.startLayerName, @@ -1084,14 +1084,31 @@ ${escapedMessage} property.value = propertyValue; } - private setLayerVisibility(layerName: string, visible: boolean): void { - const phaserLayer = this.gameMap.findPhaserLayer(layerName); - if (phaserLayer === undefined) { - console.warn('Could not find layer "' + layerName + '" when calling WA.hideLayer / WA.showLayer'); - return; + private setLayerVisibility(layerName: string, visible: boolean, group: boolean): void { + if (group) { + const phaserLayers = this.gameMap.findPhaserLayers(layerName); + if (phaserLayers === []) { + console.warn( + 'Could not find layer with name that contains "' + + layerName + + '" when calling WA.hideLayer / WA.showLayer' + ); + return; + } + for (let i = 0; i < phaserLayers.length; i++) { + phaserLayers[i].setVisible(visible); + phaserLayers[i].setCollisionByProperty({ collides: true }, visible); + } + } else { + const phaserLayer = this.gameMap.findPhaserLayer(layerName); + if (phaserLayer === undefined) { + console.warn('Could not find layer "' + layerName + '" when calling WA.hideLayer / WA.showLayer'); + return; + } + phaserLayer.setVisible(visible); + phaserLayer.setCollisionByProperty({ collides: true }, visible); } - phaserLayer.setVisible(visible); - this.dirty = true; + this.markDirty(); } private getMapDirUrl(): string { @@ -1147,7 +1164,7 @@ ${escapedMessage} this.emoteManager.destroy(); this.peerStoreUnsubscribe(); this.biggestAvailableAreaStoreUnsubscribe(); - iframeListener.unregisterAnswerer('getState'); + iframeListener.unregisterAnswerer("getState"); mediaManager.hideGameOverlay(); From bef5e139c0d5fbcada2925bc5a3a54836986fdf7 Mon Sep 17 00:00:00 2001 From: GRL Date: Wed, 7 Jul 2021 14:42:17 +0200 Subject: [PATCH 2/7] SetTiles can now set a tile to null so that there is no more tile. --- front/src/Api/Events/SetTilesEvent.ts | 2 +- front/src/Api/iframe/room.ts | 4 ++-- front/src/Phaser/Game/GameMap.ts | 33 +++++++++++++++++++-------- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/front/src/Api/Events/SetTilesEvent.ts b/front/src/Api/Events/SetTilesEvent.ts index c7f8f16d..371f0884 100644 --- a/front/src/Api/Events/SetTilesEvent.ts +++ b/front/src/Api/Events/SetTilesEvent.ts @@ -5,7 +5,7 @@ export const isSetTilesEvent = tg.isArray( .withProperties({ x: tg.isNumber, y: tg.isNumber, - tile: tg.isUnion(tg.isNumber, tg.isString), + tile: tg.isUnion(tg.isUnion(tg.isNumber, tg.isString), tg.isNull), layer: tg.isString, }) .get() diff --git a/front/src/Api/iframe/room.ts b/front/src/Api/iframe/room.ts index c70d0aad..a9ee52ce 100644 --- a/front/src/Api/iframe/room.ts +++ b/front/src/Api/iframe/room.ts @@ -4,7 +4,7 @@ import { isDataLayerEvent } from "../Events/DataLayerEvent"; import { EnterLeaveEvent, isEnterLeaveEvent } from "../Events/EnterLeaveEvent"; import { isGameStateEvent } from "../Events/GameStateEvent"; -import {IframeApiContribution, queryWorkadventure, sendToWorkadventure} from "./IframeApiContribution"; +import { IframeApiContribution, queryWorkadventure, sendToWorkadventure } from "./IframeApiContribution"; import { apiCallback } from "./registeredCallbacks"; import type { ITiledMap } from "../../Phaser/Map/ITiledMap"; @@ -34,7 +34,7 @@ interface User { interface TileDescriptor { x: number; y: number; - tile: number | string; + tile: number | string | null; layer: string; } diff --git a/front/src/Phaser/Game/GameMap.ts b/front/src/Phaser/Game/GameMap.ts index a616cf4a..1f232265 100644 --- a/front/src/Phaser/Game/GameMap.ts +++ b/front/src/Phaser/Game/GameMap.ts @@ -152,7 +152,10 @@ export class GameMap { } private getTileProperty(index: number): Array { - return this.tileSetPropertyMap[index]; + if (this.tileSetPropertyMap[index]) { + return this.tileSetPropertyMap[index]; + } + return []; } private trigger( @@ -198,37 +201,49 @@ export class GameMap { private putTileInFlatLayer(index: number, x: number, y: number, layer: string): void { const fLayer = this.findLayer(layer); if (fLayer == undefined) { - console.error("The layer that you want to change doesn't exist."); + console.error("The layer '" + layer + "' that you want to change doesn't exist."); return; } if (fLayer.type !== "tilelayer") { - console.error("The layer that you want to change is not a tilelayer. Tile can only be put in tilelayer."); + console.error( + "The layer '" + + layer + + "' that you want to change is not a tilelayer. Tile can only be put in tilelayer." + ); return; } if (typeof fLayer.data === "string") { - console.error("Data of the layer that you want to change is only readable."); + console.error("Data of the layer '" + layer + "' that you want to change is only readable."); return; } - fLayer.data[x + y * fLayer.height] = index; + fLayer.data[x + y * fLayer.width] = index; } - public putTile(tile: string | number, x: number, y: number, layer: string): void { + public putTile(tile: string | number | null, x: number, y: number, layer: string): void { const phaserLayer = this.findPhaserLayer(layer); if (phaserLayer) { + if (tile === null) { + phaserLayer.putTileAt(-1, x, y); + return; + } const tileIndex = this.getIndexForTileType(tile); if (tileIndex !== undefined) { this.putTileInFlatLayer(tileIndex, x, y, layer); const phaserTile = phaserLayer.putTileAt(tileIndex, x, y); for (const property of this.getTileProperty(tileIndex)) { - if (property.name === "collides" && property.value === "true") { + if (property.name === "collides" && property.value) { phaserTile.setCollision(true); } } } else { - console.error("The tile that you want to place doesn't exist."); + console.error("The tile '" + tile + "' that you want to place doesn't exist."); } } else { - console.error("The layer that you want to change is not a tilelayer. Tile can only be put in tilelayer."); + console.error( + "The layer '" + + layer + + "' that you want to change is not a tilelayer. Tile can only be put in tilelayer." + ); } } From 24811e0a31a70a4d32fe3fda16d0f71274d6f872 Mon Sep 17 00:00:00 2001 From: GRL Date: Wed, 7 Jul 2021 14:59:40 +0200 Subject: [PATCH 3/7] SetProperty delete a property where tha value is undefined and load the map of exitUrl property --- front/src/Phaser/Game/GameScene.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index d6df242f..6427e0c0 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -1077,14 +1077,24 @@ ${escapedMessage} console.warn('Could not find layer "' + layerName + '" when calling setProperty'); return; } + if (propertyName === "exitUrl" && typeof propertyValue === "string") { + this.loadNextGame(propertyValue); + } if (layer.properties === undefined) { layer.properties = []; } const property = layer.properties.find((property) => property.name === propertyName); if (property === undefined) { + if (propertyValue === undefined) { + return; + } layer.properties.push({ name: propertyName, type: typeof propertyValue, value: propertyValue }); return; } + if (propertyValue === undefined) { + const index = layer.properties.indexOf(property); + layer.properties.splice(index, 1); + } property.value = propertyValue; } From 17525e1e158256023efda437e88a1f04f4d2bef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?gr=C3=A9goire=20parant?= Date: Wed, 7 Jul 2021 16:42:26 +0200 Subject: [PATCH 4/7] Return at the new line into the Pop-up (#1267) Add regex to replace "\r\n" or "\r" or "\n" by
--- front/src/WebRtc/HtmlUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front/src/WebRtc/HtmlUtils.ts b/front/src/WebRtc/HtmlUtils.ts index 942e553f..569abd07 100644 --- a/front/src/WebRtc/HtmlUtils.ts +++ b/front/src/WebRtc/HtmlUtils.ts @@ -25,7 +25,7 @@ export class HtmlUtils { } public static escapeHtml(html: string): string { - const text = document.createTextNode(html); + const text = document.createTextNode(html.replace(/(\r\n|\r|\n)/g,'
')); const p = document.createElement('p'); p.appendChild(text); return p.innerHTML; From e50292a2ba42814fd6759df68abef10b26a3723b Mon Sep 17 00:00:00 2001 From: GRL Date: Wed, 7 Jul 2021 16:58:54 +0200 Subject: [PATCH 5/7] Add documentation No second parameter --- docs/maps/api-room.md | 4 ++++ front/src/Api/Events/LayerEvent.ts | 1 - front/src/Api/iframe/room.ts | 8 ++++---- front/src/Phaser/Game/GameScene.ts | 22 +++++++++------------- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/docs/maps/api-room.md b/docs/maps/api-room.md index 9d08ce1b..86886567 100644 --- a/docs/maps/api-room.md +++ b/docs/maps/api-room.md @@ -54,6 +54,7 @@ WA.room.showLayer(layerName : string): void WA.room.hideLayer(layerName : string) : void ``` These 2 methods can be used to show and hide a layer. +if `layerName` is the name of a group layer, show/hide all the layer in that group layer. Example : ```javascript @@ -70,6 +71,9 @@ WA.room.setProperty(layerName : string, propertyName : string, propertyValue : s Set the value of the `propertyName` property of the layer `layerName` at `propertyValue`. If the property doesn't exist, create the property `propertyName` and set the value of the property at `propertyValue`. +Note : +To unset a property form a layer, use `setProperty` with `propertyValue` set to `undefined`. + Example : ```javascript WA.room.setProperty('wikiLayer', 'openWebsite', 'https://www.wikipedia.org/'); diff --git a/front/src/Api/Events/LayerEvent.ts b/front/src/Api/Events/LayerEvent.ts index d3fdda22..b56c3163 100644 --- a/front/src/Api/Events/LayerEvent.ts +++ b/front/src/Api/Events/LayerEvent.ts @@ -3,7 +3,6 @@ import * as tg from "generic-type-guard"; export const isLayerEvent = new tg.IsInterface() .withProperties({ name: tg.isString, - group: tg.isBoolean, }) .get(); /** diff --git a/front/src/Api/iframe/room.ts b/front/src/Api/iframe/room.ts index 8ff31375..deee0e2a 100644 --- a/front/src/Api/iframe/room.ts +++ b/front/src/Api/iframe/room.ts @@ -93,11 +93,11 @@ export class WorkadventureRoomCommands extends IframeApiContribution { - this.setLayerVisibility(layerEvent.name, true, layerEvent.group); + this.setLayerVisibility(layerEvent.name, true); }) ); this.iframeSubscriptionList.push( iframeListener.hideLayerStream.subscribe((layerEvent) => { - this.setLayerVisibility(layerEvent.name, false, layerEvent.group); + this.setLayerVisibility(layerEvent.name, false); }) ); @@ -1088,9 +1088,13 @@ ${escapedMessage} property.value = propertyValue; } - private setLayerVisibility(layerName: string, visible: boolean, group: boolean): void { - if (group) { - const phaserLayers = this.gameMap.findPhaserLayers(layerName); + private setLayerVisibility(layerName: string, visible: boolean): void { + const phaserLayer = this.gameMap.findPhaserLayer(layerName); + if (phaserLayer != undefined) { + phaserLayer.setVisible(visible); + phaserLayer.setCollisionByProperty({ collides: true }, visible); + } else { + const phaserLayers = this.gameMap.findPhaserLayers(layerName + "/"); if (phaserLayers === []) { console.warn( 'Could not find layer with name that contains "' + @@ -1103,14 +1107,6 @@ ${escapedMessage} phaserLayers[i].setVisible(visible); phaserLayers[i].setCollisionByProperty({ collides: true }, visible); } - } else { - const phaserLayer = this.gameMap.findPhaserLayer(layerName); - if (phaserLayer === undefined) { - console.warn('Could not find layer "' + layerName + '" when calling WA.hideLayer / WA.showLayer'); - return; - } - phaserLayer.setVisible(visible); - phaserLayer.setCollisionByProperty({ collides: true }, visible); } this.markDirty(); } From 64c569c42f6bf0b1edd1ee039551c7aff0132bb8 Mon Sep 17 00:00:00 2001 From: GRL Date: Wed, 7 Jul 2021 17:06:23 +0200 Subject: [PATCH 6/7] Add documentation and CHANGELOG Modify error message --- CHANGELOG.md | 4 ++-- docs/maps/api-room.md | 1 + front/src/Phaser/Game/GameMap.ts | 6 +----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a83e8213..ff7496ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,12 +10,12 @@ - New scripting API features : - Use `WA.room.showLayer(): void` to show a layer - Use `WA.room.hideLayer(): void` to hide a layer - - Use `WA.room.setProperty() : void` to add or change existing property of a layer + - Use `WA.room.setProperty() : void` to add, delete or change existing property of a layer - Use `WA.player.onPlayerMove(): void` to track the movement of the current player - Use `WA.room.getCurrentUser(): Promise` to get the ID, name and tags of the current player - Use `WA.room.getCurrentRoom(): Promise` 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.ui.registerMenuCommand(): void` to add a custom menu - - Use `WA.room.setTiles(): void` to change an array of tiles + - Use `WA.room.setTiles(): void` to add, delete or change an array of tiles - Users blocking now relies on UUID rather than ID. A blocked user that leaves a room and comes back will stay blocked. ## Version 1.4.3 - 1.4.4 - 1.4.5 diff --git a/docs/maps/api-room.md b/docs/maps/api-room.md index 9d08ce1b..22735f6c 100644 --- a/docs/maps/api-room.md +++ b/docs/maps/api-room.md @@ -134,6 +134,7 @@ If `tile` is a string, it's not the id of the tile but the value of the property **Important !** : If you use `tile` as a number, be sure to add the `firstgid` of the tileset of the tile that you want to the id of the tile in Tiled Editor. +Note: If you want to unset a tile, use `setTiles` with `tile` set to `null`. Example : ```javascript diff --git a/front/src/Phaser/Game/GameMap.ts b/front/src/Phaser/Game/GameMap.ts index 1f232265..99a1edad 100644 --- a/front/src/Phaser/Game/GameMap.ts +++ b/front/src/Phaser/Game/GameMap.ts @@ -239,11 +239,7 @@ export class GameMap { console.error("The tile '" + tile + "' that you want to place doesn't exist."); } } else { - console.error( - "The layer '" + - layer + - "' that you want to change is not a tilelayer. Tile can only be put in tilelayer." - ); + console.error("The layer '" + layer + "' does not exist (or is not a tilelaye)."); } } From cb5bdb5fea0d800bfecc235e78995d9650facf0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Wed, 7 Jul 2021 17:15:22 +0200 Subject: [PATCH 7/7] Fixing typo --- docs/maps/api-room.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/maps/api-room.md b/docs/maps/api-room.md index 86886567..93cb732a 100644 --- a/docs/maps/api-room.md +++ b/docs/maps/api-room.md @@ -72,7 +72,7 @@ WA.room.setProperty(layerName : string, propertyName : string, propertyValue : s Set the value of the `propertyName` property of the layer `layerName` at `propertyValue`. If the property doesn't exist, create the property `propertyName` and set the value of the property at `propertyValue`. Note : -To unset a property form a layer, use `setProperty` with `propertyValue` set to `undefined`. +To unset a property from a layer, use `setProperty` with `propertyValue` set to `undefined`. Example : ```javascript