From 3a00ecab8f1e4d29c683686322649e73b45e4722 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 May 2021 13:44:51 +0000 Subject: [PATCH 1/9] Bump lodash from 4.17.20 to 4.17.21 in /uploader Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21) Signed-off-by: dependabot[bot] --- uploader/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uploader/yarn.lock b/uploader/yarn.lock index 1591fa3e..92253d44 100644 --- a/uploader/yarn.lock +++ b/uploader/yarn.lock @@ -1105,9 +1105,9 @@ lodash.once@^4.0.0: integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== loud-rejection@^1.0.0: version "1.6.0" From 9c620de649a6cf87ae674700ecf9f5b32d4c8eb9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 May 2021 13:45:25 +0000 Subject: [PATCH 2/9] Bump lodash from 4.17.20 to 4.17.21 in /maps Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21) Signed-off-by: dependabot[bot] --- maps/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/maps/yarn.lock b/maps/yarn.lock index d2393a65..ffb4747a 100644 --- a/maps/yarn.lock +++ b/maps/yarn.lock @@ -881,9 +881,9 @@ loader-utils@^2.0.0: json5 "^2.1.2" lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== loud-rejection@^1.0.0: version "1.6.0" From 543397efe48be43926b340a2e285ac1edbf2f53e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 May 2021 13:45:29 +0000 Subject: [PATCH 3/9] Bump lodash from 4.17.20 to 4.17.21 in /messages Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21) Signed-off-by: dependabot[bot] --- messages/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/messages/yarn.lock b/messages/yarn.lock index d520d465..81bd0ed1 100644 --- a/messages/yarn.lock +++ b/messages/yarn.lock @@ -2606,9 +2606,9 @@ lodash.templatesettings@^4.0.0: lodash._reinterpolate "^3.0.0" lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== log-ok@^0.1.1: version "0.1.1" From b141da14753ac3df923fcb5bb7ecc8635a3b7f4a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 May 2021 13:45:33 +0000 Subject: [PATCH 4/9] Bump lodash from 4.17.20 to 4.17.21 in /back Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21) Signed-off-by: dependabot[bot] --- back/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/back/yarn.lock b/back/yarn.lock index 43f58988..9469a69d 100644 --- a/back/yarn.lock +++ b/back/yarn.lock @@ -1704,9 +1704,9 @@ lodash.once@^4.0.0: integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== long@~3: version "3.2.0" From bc88a7d3edafb8a90e36bb96767e8d33dfdd215f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 10 May 2021 10:47:55 +0200 Subject: [PATCH 5/9] Adding Markdown documentation relative to scripting --- docs/maps/scripting.md | 348 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 348 insertions(+) create mode 100644 docs/maps/scripting.md diff --git a/docs/maps/scripting.md b/docs/maps/scripting.md new file mode 100644 index 00000000..f844154c --- /dev/null +++ b/docs/maps/scripting.md @@ -0,0 +1,348 @@ +{.alert.alert-danger} +This feature is "_experimental_". We may apply changes in the near future to the way it works when we gather some feedback. + +{.section-title.accent.text-primary} +# Scripting WorkAdventure maps + +Do you want to add a bit of intelligence to your map? Scripts allow you to create maps with special features. + +You can for instance: + +* Create FTUE (First Time User Experience) scenarios where a first-time user will be displayed a notification popup. +* Create NPC (non playing characters) and interact with those characters using the chat. +* Organize interactions between an iframe and your map (for instance, walking on a special zone might add a product in the cart of an eCommerce website...) +* etc... + +Please note that scripting in WorkAdventure is at an early stage of development and that more features might be added in the future. You can actually voice your opinion about useful features by adding [an issue on Github](https://github.com/thecodingmachine/workadventure/issues). + +{.alert.alert-warning} +**Beware:** Scripts are executed in the browser of the current user only. Generally speaking, scripts cannot be used to trigger a change that will be displayed on other users screen. + +## Scripting language + +Client-side scripting is done in **Javascript** (or any language that transpiles to Javascript like _Typescript_). + +There are 2 ways you can use the scripting language: + +* **In the map**: By directly referring a Javascript file inside your map, in the `script` property of your map. +* **In an iFrame**: By placing your Javascript script into an iFrame, your script can communicate with the WorkAdventure game + +## Adding a script in the map + +Create a `script` property in your map. + +In Tiled, in order to access your map properties, you can click on _"Map > Map properties"_. + +
+
+ +
The Map properties menu
+
+
+ +Create a `script` property (a "string"), and put the URL of your script. + +You can put relative URLs. If your script file is next to your map, you can simply write the name of the script file here. + +
+
+ +
The script property
+
+
+ +Start by testing this with a simple message sent to the chat. + +**script.js** +```javascript +WA.sendChatMessage('Hello world', 'Mr Robot'); +``` + +The `WA` objects contains a number of useful methods enabling you to interact with the WorkAdventure game. For instance, `WA.sendChatMessage` opens the chat and adds a message in it. + +In your browser console, when you open the map, the chat message should be displayed right away. + +## Adding a script in an iFrame + +In WorkAdventure, you can easily [open an iFrame using the `openWebsite` property on a layer](special-zones). However, by default, the iFrame is not allowed to communicate with WorkAdventure. + +This is done to improve security. In order to be able to execute a script that communicates with WorkAdventure inside an iFrame, you have to **explicitly allow the iFrame to use the "iFrame API"**. + +In order to allow communication with WorkAdventure, you need to add an additional property: `openWebsiteAllowApi`. This property must be _boolean_ and you must set it to "true". + +
+
+ +
The `openWebsiteAllowApi` property
+
+
+ +In your iFrame HTML page, you now need to import the _WorkAdventure client API Javascript library_. This library contains the `WA` object that you can use to communicate with WorkAdventure. + +The library is available at `https://play.workadventu.re/iframe_api.js`. + +_Note:_ if you are using a self-hosted version of WorkAdventure, use `https://[front_domain]/iframe_api.js` + +**iframe.html** +```html + + + + + + + + +``` + +You can now start by testing this with a simple message sent to the chat. + +**iframe.html** +```html +... + +... +``` + +Let's now review the complete list of methods available in this `WA` object. + +## Using Typescript + +View the dedicated page about [using Typescript with the scripting API](using-typescript). + +## Available features in the client API + +### Sending a message in the chat + + sendChatMessage(message: string, author: string): void + +Sends a message in the chat. The message is only visible in the browser of the current user. + +* **message**: the message to be displayed in the chat +* **author**: the name displayed for the author of the message. It does not have to be a real user. + +Example: + +```javascript +WA.sendChatMessage('Hello world', 'Mr Robot'); +``` + +### Listening to messages from the chat + +```javascript +onChatMessage(callback: (message: string) => void): void +``` + +Listens to messages typed by the current user and calls the callback. Messages from other users in the chat cannot be listened to. + +* **callback**: the function that will be called when a message is received. It contains the message typed by the user. + +Example: + +```javascript +WA.onChatMessage((message => { + console.log('The user typed a message', message); +})); +``` + +### Detecting when the user enters/leaves a zone + +``` +onEnterZone(name: string, callback: () => void): void +onLeaveZone(name: string, callback: () => void): void +``` + +Listens to the position of the current user. The event is triggered when the user enters or leaves a given zone. The name of the zone is stored in the map, on a dedicated layer with the `zone` property. + +
+
+ +
The `zone` property, applied on a layer
+
+
+ +* **name**: the name of the zone, as defined in the `zone` property. +* **callback**: the function that will be called when a user enters or leaves the zone. + +Example: + +```javascript +WA.onEnterZone('myZone', () => { + WA.sendChatMessage("Hello!", 'Mr Robot'); +}) + +WA.onLeaveZone('myZone', () => { + WA.sendChatMessage("Goodbye!", 'Mr Robot'); +}) +``` + +### Opening a popup + +In order to open a popup window, you must first define the position of the popup on your map. + +You can position this popup by using a "rectangle" object in Tiled that you will place on an "object" layer. + +
+
+ +
+
+ +
+
+ +``` +openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup +``` + +* **targetObject**: the name of the rectangle object defined in Tiled. +* **message**: the message to display in the popup. +* **buttons**: an array of action buttons defined underneath the popup. + +Action buttons are `ButtonDescriptor` objects containing these properties. + +* **label (_string_)**: The label of the button. +* **className (_string_)**: The visual type of the button. Can be one of "normal", "primary", "success", "warning", "error", "disabled". +* **callback (_(popup: Popup)=>void_)**: Callback called when the button is pressed. + +Please note that `openPopup` returns an object of the `Popup` class. Also, the callback called when a button is clicked is passed a `Popup` object. + +The `Popup` class that represents an open popup contains a single method: `close()`. This will obviously close the popup when called. + +```javascript +class Popup { + /** + * Closes the popup + */ + close() {}; +} +``` + +Example: + +```javascript +let helloWorldPopup; + +// Open the popup when we enter a given zone +helloWorldPopup = WA.onEnterZone('myZone', () => { + WA.openPopup("popupRectangle", 'Hello world!', [{ + label: "Close", + className: "primary", + callback: (popup) => { + // Close the popup when the "Close" button is pressed. + popup.close(); + } + }); +}]); + +// Close the popup when we leave the zone. +WA.onLeaveZone('myZone', () => { + helloWorldPopup.close(); +}); +``` + +### Disabling / restoring controls + +``` +disablePlayerControls(): void +restorePlayerControls(): void +``` + +These 2 methods can be used to completely disable player controls and to enable them again. + +When controls are disabled, the user cannot move anymore using keyboard input. This can be useful in a "First Time User Experience" part, to display an important message to a user before letting him/her move again. + +Example: + +```javascript +WA.onEnterZone('myZone', () => { + WA.disablePlayerControls(); + WA.openPopup("popupRectangle", 'This is an imporant message!', [{ + label: "Got it!", + className: "primary", + callback: (popup) => { + WA.restorePlayerControls(); + popup.close(); + } + }]); +}); +``` + +### Opening a web page in a new tab + +``` +openTab(url: string): void +``` + +Opens the webpage at "url" in your browser, in a new tab. + +Example: + +```javascript +WA.openTab('https://www.wikipedia.org/'); +``` + +### Opening a web page in the current tab + +``` +goToPage(url: string): void +``` + +Opens the webpage at "url" in your browser in place of WorkAdventure. WorkAdventure will be completely unloaded. + +Example: + +```javascript +WA.goToPage('https://www.wikipedia.org/'); +``` + +### Opening/closing a web page in an iFrame + +``` +openCoWebSite(url: string): void +closeCoWebSite(): void +``` + +Opens the webpage at "url" in an iFrame (on the right side of the screen) or close that iFrame. + +Example: + +```javascript +WA.openCoWebSite('https://www.wikipedia.org/'); +// ... +WA.closeCoWebSite(); +``` + +### Load a sound from an url + +``` +loadSound(url: string): Sound +``` + +Load a sound from an url + +Please note that `loadSound` returns an object of the `Sound` class + +The `Sound` class that represents a loaded sound contains two methods: `play(soundConfig : SoundConfig|undefined)` and `stop()` + +The parameter soundConfig is optional, if you call play without a Sound config the sound will be played with the basic configuration. + +Example: + +```javascript +var mySound = WA.loadSound("Sound.ogg"); +var config = { + volume : 0.5, + loop : false, + rate : 1, + detune : 1, + delay : 0, + seek : 0, + mute : false +} +mySound.play(config); +// ... +mySound.stop(); +``` From 9a8b10bbf5c9ac178fc0b5bc767ea8ee1cb18837 Mon Sep 17 00:00:00 2001 From: kharhamel Date: Mon, 10 May 2021 11:56:08 +0200 Subject: [PATCH 6/9] added back automatic deploy of staging --- .github/workflows/build-and-deploy.yml | 30 ++++++++++++++------------ 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 9e22dedc..42f4868b 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -1,6 +1,8 @@ name: Build, push and deploy Docker image on: + push: + branch: [master] release: types: [created] pull_request: @@ -14,7 +16,7 @@ env: jobs: build-front: - if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }} + if: ${{ github.event.release || github.event.push || contains(github.event.pull_request.labels.*.name, 'deploy') }} runs-on: ubuntu-latest steps: @@ -34,11 +36,11 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} repository: thecodingmachine/workadventure-front - tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }} + tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || github.event.release && env.GITHUB_REF_SLUG || 'master' }} add_git_labels: true build-back: - if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }} + if: ${{ github.event.release || github.event.push || contains(github.event.pull_request.labels.*.name, 'deploy') }} runs-on: ubuntu-latest steps: @@ -57,11 +59,11 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} repository: thecodingmachine/workadventure-back - tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }} + tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || github.event.release && env.GITHUB_REF_SLUG || 'master' }} add_git_labels: true build-pusher: - if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }} + if: ${{ github.event.release || github.event.push || contains(github.event.pull_request.labels.*.name, 'deploy') }} runs-on: ubuntu-latest steps: @@ -80,11 +82,11 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} repository: thecodingmachine/workadventure-pusher - tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }} + tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || github.event.release && env.GITHUB_REF_SLUG || 'master' }} add_git_labels: true build-uploader: - if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }} + if: ${{ github.event.release || github.event.push || contains(github.event.pull_request.labels.*.name, 'deploy') }} runs-on: ubuntu-latest steps: @@ -103,11 +105,11 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} repository: thecodingmachine/workadventure-uploader - tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }} + tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || github.event.release && env.GITHUB_REF_SLUG || 'master' }} add_git_labels: true build-maps: - if: ${{ github.event.release || contains(github.event.pull_request.labels.*.name, 'deploy') }} + if: ${{ github.event.release || github.event.push || contains(github.event.pull_request.labels.*.name, 'deploy') }} runs-on: ubuntu-latest steps: @@ -127,7 +129,7 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} repository: thecodingmachine/workadventure-maps - tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }} + tags: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || github.event.release && env.GITHUB_REF_SLUG || 'master' }} add_git_labels: true deeploy: @@ -138,7 +140,7 @@ jobs: - build-maps - build-uploader runs-on: ubuntu-latest - if: ${{ contains(github.event.pull_request.labels.*.name, 'deploy') }} + if: ${{ github.event.push || contains(github.event.pull_request.labels.*.name, 'deploy') }} steps: - name: Checkout @@ -156,14 +158,14 @@ jobs: JITSI_URL: ${{ secrets.JITSI_URL }} SECRET_JITSI_KEY: ${{ secrets.SECRET_JITSI_KEY }} TURN_STATIC_AUTH_SECRET: ${{ secrets.TURN_STATIC_AUTH_SECRET }} - DEPLOY_REF: ${{ env.GITHUB_HEAD_REF_SLUG }} + DEPLOY_REF: ${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || 'master' }} with: - namespace: workadventure-${{ env.GITHUB_HEAD_REF_SLUG }} + namespace: workadventure-${{ github.event.pull_request && env.GITHUB_HEAD_REF_SLUG || 'master' }} - name: Add a comment in PR uses: unsplash/comment-on-pr@v1.2.0 + if: ${{ github.event.pull_request }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: msg: Environment deployed at https://play.${{ env.GITHUB_HEAD_REF_SLUG }}.test.workadventu.re - check_for_duplicate_msg: true From 293c57568e42d4e53434608947a8e4662ce84775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 10 May 2021 12:08:52 +0200 Subject: [PATCH 7/9] Splitting scripting API doc in 2 Splitting scripting API doc in 2 docs: - scripting.md: contains the explaination on how to enable scripting - api-reference.md: contains the list of all available functions --- docs/maps/api-reference.md | 237 +++++++++++++++++++++++++++++++++++++ docs/maps/scripting.md | 233 +----------------------------------- 2 files changed, 238 insertions(+), 232 deletions(-) create mode 100644 docs/maps/api-reference.md diff --git a/docs/maps/api-reference.md b/docs/maps/api-reference.md new file mode 100644 index 00000000..9891a88a --- /dev/null +++ b/docs/maps/api-reference.md @@ -0,0 +1,237 @@ +{.section-title.accent.text-primary} +# API Reference + +### Sending a message in the chat + +``` +sendChatMessage(message: string, author: string): void +``` + +Sends a message in the chat. The message is only visible in the browser of the current user. + +* **message**: the message to be displayed in the chat +* **author**: the name displayed for the author of the message. It does not have to be a real user. + +Example: + +```javascript +WA.sendChatMessage('Hello world', 'Mr Robot'); +``` + +### Listening to messages from the chat + +```javascript +onChatMessage(callback: (message: string) => void): void +``` + +Listens to messages typed by the current user and calls the callback. Messages from other users in the chat cannot be listened to. + +* **callback**: the function that will be called when a message is received. It contains the message typed by the user. + +Example: + +```javascript +WA.onChatMessage((message => { + console.log('The user typed a message', message); +})); +``` + +### Detecting when the user enters/leaves a zone + +``` +onEnterZone(name: string, callback: () => void): void +onLeaveZone(name: string, callback: () => void): void +``` + +Listens to the position of the current user. The event is triggered when the user enters or leaves a given zone. The name of the zone is stored in the map, on a dedicated layer with the `zone` property. + +
+
+ +
The `zone` property, applied on a layer
+
+
+ +* **name**: the name of the zone, as defined in the `zone` property. +* **callback**: the function that will be called when a user enters or leaves the zone. + +Example: + +```javascript +WA.onEnterZone('myZone', () => { + WA.sendChatMessage("Hello!", 'Mr Robot'); +}) + +WA.onLeaveZone('myZone', () => { + WA.sendChatMessage("Goodbye!", 'Mr Robot'); +}) +``` + +### Opening a popup + +In order to open a popup window, you must first define the position of the popup on your map. + +You can position this popup by using a "rectangle" object in Tiled that you will place on an "object" layer. + +
+
+ +
+
+ +
+
+ +``` +openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup +``` + +* **targetObject**: the name of the rectangle object defined in Tiled. +* **message**: the message to display in the popup. +* **buttons**: an array of action buttons defined underneath the popup. + +Action buttons are `ButtonDescriptor` objects containing these properties. + +* **label (_string_)**: The label of the button. +* **className (_string_)**: The visual type of the button. Can be one of "normal", "primary", "success", "warning", "error", "disabled". +* **callback (_(popup: Popup)=>void_)**: Callback called when the button is pressed. + +Please note that `openPopup` returns an object of the `Popup` class. Also, the callback called when a button is clicked is passed a `Popup` object. + +The `Popup` class that represents an open popup contains a single method: `close()`. This will obviously close the popup when called. + +```javascript +class Popup { + /** + * Closes the popup + */ + close() {}; +} +``` + +Example: + +```javascript +let helloWorldPopup; + +// Open the popup when we enter a given zone +helloWorldPopup = WA.onEnterZone('myZone', () => { + WA.openPopup("popupRectangle", 'Hello world!', [{ + label: "Close", + className: "primary", + callback: (popup) => { + // Close the popup when the "Close" button is pressed. + popup.close(); + } + }); +}]); + +// Close the popup when we leave the zone. +WA.onLeaveZone('myZone', () => { + helloWorldPopup.close(); +}); +``` + +### Disabling / restoring controls + +``` +disablePlayerControls(): void +restorePlayerControls(): void +``` + +These 2 methods can be used to completely disable player controls and to enable them again. + +When controls are disabled, the user cannot move anymore using keyboard input. This can be useful in a "First Time User Experience" part, to display an important message to a user before letting him/her move again. + +Example: + +```javascript +WA.onEnterZone('myZone', () => { + WA.disablePlayerControls(); + WA.openPopup("popupRectangle", 'This is an imporant message!', [{ + label: "Got it!", + className: "primary", + callback: (popup) => { + WA.restorePlayerControls(); + popup.close(); + } + }]); +}); +``` + +### Opening a web page in a new tab + +``` +openTab(url: string): void +``` + +Opens the webpage at "url" in your browser, in a new tab. + +Example: + +```javascript +WA.openTab('https://www.wikipedia.org/'); +``` + +### Opening a web page in the current tab + +``` +goToPage(url: string): void +``` + +Opens the webpage at "url" in your browser in place of WorkAdventure. WorkAdventure will be completely unloaded. + +Example: + +```javascript +WA.goToPage('https://www.wikipedia.org/'); +``` + +### Opening/closing a web page in an iFrame + +``` +openCoWebSite(url: string): void +closeCoWebSite(): void +``` + +Opens the webpage at "url" in an iFrame (on the right side of the screen) or close that iFrame. + +Example: + +```javascript +WA.openCoWebSite('https://www.wikipedia.org/'); +// ... +WA.closeCoWebSite(); +``` + +### Load a sound from an url + +``` +loadSound(url: string): Sound +``` + +Load a sound from an url + +Please note that `loadSound` returns an object of the `Sound` class + +The `Sound` class that represents a loaded sound contains two methods: `play(soundConfig : SoundConfig|undefined)` and `stop()` + +The parameter soundConfig is optional, if you call play without a Sound config the sound will be played with the basic configuration. + +Example: + +```javascript +var mySound = WA.loadSound("Sound.ogg"); +var config = { + volume : 0.5, + loop : false, + rate : 1, + detune : 1, + delay : 0, + seek : 0, + mute : false +} +mySound.play(config); +// ... +mySound.stop(); +``` diff --git a/docs/maps/scripting.md b/docs/maps/scripting.md index f844154c..a3dd6572 100644 --- a/docs/maps/scripting.md +++ b/docs/maps/scripting.md @@ -114,235 +114,4 @@ View the dedicated page about [using Typescript with the scripting API](using-ty ## Available features in the client API -### Sending a message in the chat - - sendChatMessage(message: string, author: string): void - -Sends a message in the chat. The message is only visible in the browser of the current user. - -* **message**: the message to be displayed in the chat -* **author**: the name displayed for the author of the message. It does not have to be a real user. - -Example: - -```javascript -WA.sendChatMessage('Hello world', 'Mr Robot'); -``` - -### Listening to messages from the chat - -```javascript -onChatMessage(callback: (message: string) => void): void -``` - -Listens to messages typed by the current user and calls the callback. Messages from other users in the chat cannot be listened to. - -* **callback**: the function that will be called when a message is received. It contains the message typed by the user. - -Example: - -```javascript -WA.onChatMessage((message => { - console.log('The user typed a message', message); -})); -``` - -### Detecting when the user enters/leaves a zone - -``` -onEnterZone(name: string, callback: () => void): void -onLeaveZone(name: string, callback: () => void): void -``` - -Listens to the position of the current user. The event is triggered when the user enters or leaves a given zone. The name of the zone is stored in the map, on a dedicated layer with the `zone` property. - -
-
- -
The `zone` property, applied on a layer
-
-
- -* **name**: the name of the zone, as defined in the `zone` property. -* **callback**: the function that will be called when a user enters or leaves the zone. - -Example: - -```javascript -WA.onEnterZone('myZone', () => { - WA.sendChatMessage("Hello!", 'Mr Robot'); -}) - -WA.onLeaveZone('myZone', () => { - WA.sendChatMessage("Goodbye!", 'Mr Robot'); -}) -``` - -### Opening a popup - -In order to open a popup window, you must first define the position of the popup on your map. - -You can position this popup by using a "rectangle" object in Tiled that you will place on an "object" layer. - -
-
- -
-
- -
-
- -``` -openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup -``` - -* **targetObject**: the name of the rectangle object defined in Tiled. -* **message**: the message to display in the popup. -* **buttons**: an array of action buttons defined underneath the popup. - -Action buttons are `ButtonDescriptor` objects containing these properties. - -* **label (_string_)**: The label of the button. -* **className (_string_)**: The visual type of the button. Can be one of "normal", "primary", "success", "warning", "error", "disabled". -* **callback (_(popup: Popup)=>void_)**: Callback called when the button is pressed. - -Please note that `openPopup` returns an object of the `Popup` class. Also, the callback called when a button is clicked is passed a `Popup` object. - -The `Popup` class that represents an open popup contains a single method: `close()`. This will obviously close the popup when called. - -```javascript -class Popup { - /** - * Closes the popup - */ - close() {}; -} -``` - -Example: - -```javascript -let helloWorldPopup; - -// Open the popup when we enter a given zone -helloWorldPopup = WA.onEnterZone('myZone', () => { - WA.openPopup("popupRectangle", 'Hello world!', [{ - label: "Close", - className: "primary", - callback: (popup) => { - // Close the popup when the "Close" button is pressed. - popup.close(); - } - }); -}]); - -// Close the popup when we leave the zone. -WA.onLeaveZone('myZone', () => { - helloWorldPopup.close(); -}); -``` - -### Disabling / restoring controls - -``` -disablePlayerControls(): void -restorePlayerControls(): void -``` - -These 2 methods can be used to completely disable player controls and to enable them again. - -When controls are disabled, the user cannot move anymore using keyboard input. This can be useful in a "First Time User Experience" part, to display an important message to a user before letting him/her move again. - -Example: - -```javascript -WA.onEnterZone('myZone', () => { - WA.disablePlayerControls(); - WA.openPopup("popupRectangle", 'This is an imporant message!', [{ - label: "Got it!", - className: "primary", - callback: (popup) => { - WA.restorePlayerControls(); - popup.close(); - } - }]); -}); -``` - -### Opening a web page in a new tab - -``` -openTab(url: string): void -``` - -Opens the webpage at "url" in your browser, in a new tab. - -Example: - -```javascript -WA.openTab('https://www.wikipedia.org/'); -``` - -### Opening a web page in the current tab - -``` -goToPage(url: string): void -``` - -Opens the webpage at "url" in your browser in place of WorkAdventure. WorkAdventure will be completely unloaded. - -Example: - -```javascript -WA.goToPage('https://www.wikipedia.org/'); -``` - -### Opening/closing a web page in an iFrame - -``` -openCoWebSite(url: string): void -closeCoWebSite(): void -``` - -Opens the webpage at "url" in an iFrame (on the right side of the screen) or close that iFrame. - -Example: - -```javascript -WA.openCoWebSite('https://www.wikipedia.org/'); -// ... -WA.closeCoWebSite(); -``` - -### Load a sound from an url - -``` -loadSound(url: string): Sound -``` - -Load a sound from an url - -Please note that `loadSound` returns an object of the `Sound` class - -The `Sound` class that represents a loaded sound contains two methods: `play(soundConfig : SoundConfig|undefined)` and `stop()` - -The parameter soundConfig is optional, if you call play without a Sound config the sound will be played with the basic configuration. - -Example: - -```javascript -var mySound = WA.loadSound("Sound.ogg"); -var config = { - volume : 0.5, - loop : false, - rate : 1, - detune : 1, - delay : 0, - seek : 0, - mute : false -} -mySound.play(config); -// ... -mySound.stop(); -``` +The list of available functions and features is [available in the API Reference page, with examples](api-reference). From c025d1798bedb9a68389d729cf15013b69ef0972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 10 May 2021 12:14:31 +0200 Subject: [PATCH 8/9] Renaming restorePlayerControls/disablePlayerControls Putting "controls" in the plural form: - restorePlayerControl => restorePlayerControls - disablePlayerControl => disablePlayerControls --- front/src/Api/Events/IframeEvent.ts | 6 +++--- front/src/Api/IframeListener.ts | 4 ++-- front/src/iframe_api.ts | 12 ++++++------ maps/Tuto/scriptTuto.js | 4 ++-- maps/tests/script.js | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/front/src/Api/Events/IframeEvent.ts b/front/src/Api/Events/IframeEvent.ts index 1ed853c9..2f703222 100644 --- a/front/src/Api/Events/IframeEvent.ts +++ b/front/src/Api/Events/IframeEvent.ts @@ -25,8 +25,8 @@ export type IframeEventMap = { goToPage: GoToPageEvent openCoWebSite: OpenCoWebSiteEvent closeCoWebSite: null - disablePlayerControl: null - restorePlayerControl: null + disablePlayerControls: null + restorePlayerControls: null displayBubble: null removeBubble: null } @@ -52,4 +52,4 @@ export interface IframeResponseEvent { } // eslint-disable-next-line @typescript-eslint/no-explicit-any -export const isIframeResponseEventWrapper = (event: { type?: string }): event is IframeResponseEvent => typeof event.type === 'string'; \ No newline at end of file +export const isIframeResponseEventWrapper = (event: { type?: string }): event is IframeResponseEvent => typeof event.type === 'string'; diff --git a/front/src/Api/IframeListener.ts b/front/src/Api/IframeListener.ts index d3b8ce4f..29e87b8a 100644 --- a/front/src/Api/IframeListener.ts +++ b/front/src/Api/IframeListener.ts @@ -96,10 +96,10 @@ class IframeListener { else if (payload.type === 'closeCoWebSite') { scriptUtils.closeCoWebSite(); } - else if (payload.type === 'disablePlayerControl') { + else if (payload.type === 'disablePlayerControls') { this._disablePlayerControlStream.next(); } - else if (payload.type === 'restorePlayerControl') { + else if (payload.type === 'restorePlayerControls') { this._enablePlayerControlStream.next(); } else if (payload.type === 'displayBubble') { diff --git a/front/src/iframe_api.ts b/front/src/iframe_api.ts index 6d0ef354..0bef1cc7 100644 --- a/front/src/iframe_api.ts +++ b/front/src/iframe_api.ts @@ -20,8 +20,8 @@ interface WorkAdventureApi { goToPage(url : string): void; openCoWebSite(url : string): void; closeCoWebSite(): void; - disablePlayerControl(): void; - restorePlayerControl(): void; + disablePlayerControls(): void; + restorePlayerControls(): void; displayBubble(): void; removeBubble(): void; } @@ -88,12 +88,12 @@ window.WA = { } as ChatEvent }, '*'); }, - disablePlayerControl(): void { - window.parent.postMessage({ 'type': 'disablePlayerControl' }, '*'); + disablePlayerControls(): void { + window.parent.postMessage({ 'type': 'disablePlayerControls' }, '*'); }, - restorePlayerControl(): void { - window.parent.postMessage({ 'type': 'restorePlayerControl' }, '*'); + restorePlayerControls(): void { + window.parent.postMessage({ 'type': 'restorePlayerControls' }, '*'); }, displayBubble(): void { diff --git a/maps/Tuto/scriptTuto.js b/maps/Tuto/scriptTuto.js index 869ec447..65962a94 100644 --- a/maps/Tuto/scriptTuto.js +++ b/maps/Tuto/scriptTuto.js @@ -25,7 +25,7 @@ function launchTuto (){ label: "Got it!", className : "success",callback:(popup2 => { popup2.close(); - WA.restorePlayerControl(); + WA.restorePlayerControls(); }) } ]) @@ -36,7 +36,7 @@ function launchTuto (){ } } ]); - WA.disablePlayerControl(); + WA.disablePlayerControls(); } diff --git a/maps/tests/script.js b/maps/tests/script.js index 25e47249..4a889a8a 100644 --- a/maps/tests/script.js +++ b/maps/tests/script.js @@ -21,7 +21,7 @@ function launchTuto (){ callback: (popup1) => { WA.sendChatMessage("Hey you can talk here too ! ", 'WA Guide'); popup1.close(); - WA.restorePlayerControl(); + WA.restorePlayerControls(); } } @@ -29,7 +29,7 @@ function launchTuto (){ } } ]); - WA.disablePlayerControl(); + WA.disablePlayerControls(); } WA.onChatMessage((message => { From 58482f8ae6aacf9d22e3fa154dae1073fcc85865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Mon, 10 May 2021 19:01:18 +0200 Subject: [PATCH 9/9] Improving Changelog --- CHANGELOG.md | 7 +++++++ docs/maps/scripting.md | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3117ea31..2028e3b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ## Version 1.3.9 - in dev +### BREAKING CHANGES + +- Scripting API: + - Changed function names: `restorePlayerControl` => `restorePlayerControls`, `disablePlayerControl` => `disablePlayerControls`. + Please keep in mind that the scripting API is still experimental. Some breaking changes can occur in it until we mark it as stable. + ### Updates - Mobile support has been improved @@ -7,6 +13,7 @@ - Mouse wheel support to zoom in / out - Pinch support on mobile to zoom in / out - Improved virtual joystick size (adapts to the zoom level) + ### Bug Fixes diff --git a/docs/maps/scripting.md b/docs/maps/scripting.md index a3dd6572..b9dee484 100644 --- a/docs/maps/scripting.md +++ b/docs/maps/scripting.md @@ -1,4 +1,4 @@ -{.alert.alert-danger} +{.alert.alert-danger style="width:80%"} This feature is "_experimental_". We may apply changes in the near future to the way it works when we gather some feedback. {.section-title.accent.text-primary}