Compare commits

...

462 Commits

Author SHA1 Message Date
Thomas Basler ca15c9f1e4 Added kitchen specific docker file 2021-05-28 19:27:06 +02:00
Thomas Basler 0249cc599f Fixed location of copyright button 2021-05-28 00:06:36 +02:00
TabascoEye e7c1ad29e2 add default value for username length 2021-05-27 22:34:38 +02:00
TabascoEye 8b0080bb21 make linter happy 2021-05-27 22:34:19 +02:00
¯\_(ツ)_/¯ 6739d68a96 modify testcases for nicknames to reflect new freedom 2021-05-27 22:34:04 +02:00
¯\_(ツ)_/¯ b27922a15f allow special chars in nicks again, make nicklength customizable 2021-05-27 22:33:44 +02:00
PizZaKatZe 9d66085623 Front federation (API and Jitsi) 2021-05-27 22:27:29 +02:00
jstsmthrgk 1981e3102f Pusher federation
Credits to infowski for the original code.
2021-05-27 22:18:51 +02:00
PizZaKatZe 98cb445dd2 Remove CI restriction to master/develop branches 2021-05-27 22:18:24 +02:00
TabascoEye 541a7edc7e delete actions which will not work on fork 2021-05-27 22:18:11 +02:00
TabascoEye ebbc16aa92 remove deploy workflow from xce fork 2021-05-27 22:16:54 +02:00
PizZaKatZe 7a07ac45c0 Add Docker rebuild/restart helper script 2021-05-27 22:16:30 +02:00
Wikinaut 1f838f2e59 Add contrib/tools/textGenerator.html
Shamelessly copied from psy's shell, improved by wikinaut and pizkaz.
2021-05-27 22:16:13 +02:00
MartiniMoe 5a68c709ca Add compose file for local development 2021-05-27 22:16:00 +02:00
TabascoEye ffd3958d4e fix Letsencrypt certificate not getting created 2021-05-27 22:15:46 +02:00
TabascoEye 4d60d8216e refactored single domain deploy and added maps container 2021-05-27 22:15:31 +02:00
¯\_(ツ)_/¯ f403bb83cb Add compose file and .env template for single domain deployment 2021-05-27 22:15:04 +02:00
¯\_(ツ)_/¯ d8d11cb008 Minor style changes 2021-05-27 22:14:44 +02:00
PizZaKatZe eb829bce58 Increase action button font size 2021-05-27 22:14:24 +02:00
PizZaKatZe 1b7de47e1b Remove 'Create map' menu entry 2021-05-27 22:14:08 +02:00
PizZaKatZe 0cedd117cd Revert "Social network link anonymous connexion"
This reverts commit 59b4b168e9.
2021-05-27 22:13:30 +02:00
PizZaKatZe f4acc29670 Load quill.js CSS locally 2021-05-27 22:13:10 +02:00
¯\_(ツ)_/¯ 1c0d30e5a2 Add copyright info button from #rc3
original code by rob@os23.de
2021-05-27 22:12:22 +02:00
Pierre Mauduit dbef5de7bb Adding a ingame console message
Roughly inspired from the code used to notify the user when a website
can be opened.

Note: The CSS style used for the message could probably go somewhere
else, but I thought it could be interesting to be able to override it.
2021-05-27 22:03:56 +02:00
TabascoEye e3af68bed3 Disable automatic gain control on microphone
AGC really makes the soundqulity way worse than it could be.
Especially since it is so noticeable when entering a Jitsi where AGC is disabled (and suddenly some people sound much better).

In the long run, this should probably be configurable. On the other hand the setting changes the audio _going out_ from a user, so it might be hard for him to judge which settings are a good or a bad idea…
2021-05-27 21:56:42 +02:00
Piotr Dobrowolski 3840baa4fc Cleanup Dockerfiles, fix front Docker image build 2021-05-27 21:54:41 +02:00
PizZaKatZe 9c8393c102 Bump Phaser version 2021-05-27 21:52:00 +02:00
Lukas von Blarer 353522e3cc Add support for HLS video streams while still supporting other formats 2021-05-27 21:47:29 +02:00
Lukas von Blarer 429a17b89b First working version of video embed 2021-05-27 21:44:58 +02:00
Johannes Berthel ea9c9ff2c3 use negative radius 2021-05-27 21:44:24 +02:00
Johannes Berthel 5ae8bfe06b fixed linting 2021-05-27 21:44:10 +02:00
Johannes Berthel a0f1f0c04b added comment for new phaser version compatibility 2021-05-27 21:43:55 +02:00
Johannes Berthel 243d4d6565 fixed hitbox calculation 2021-05-27 21:43:37 +02:00
Johannes Berthel 7fef260b38 fixed function comment 2021-05-27 21:43:20 +02:00
Johannes Berthel 359d349ba7 refactored code 2021-05-27 21:42:59 +02:00
Johannes Berthel 09ceb016b7 refactored code 2021-05-27 21:42:40 +02:00
Johannes Berthel 70d2223e00 refactored code 2021-05-27 21:42:17 +02:00
Johannes Berthel 1e1ec0ac66 removed test map 2021-05-27 21:40:48 +02:00
Johannes Berthel 4f3e0f9921 fixed depth for interactive layers 2021-05-27 21:40:30 +02:00
Johannes Berthel 1f7a3880bf made interaction work with remote players 2021-05-27 21:37:51 +02:00
Johannes Berthel 2273a84d0e added reverse animation 2021-05-27 21:36:54 +02:00
Johannes Berthel 3e20fb89ca added interaction radius 2021-05-27 21:36:14 +02:00
Johannes Berthel 66c20687c3 added basic interactive layer functionality 2021-05-27 21:34:32 +02:00
Lurkars 5946e75db0 add trigger action after closing co-website or jitsi 2021-05-27 21:07:43 +02:00
TabascoEye fa813884c0 fix bug: SPACE also mutes/unmutes audio because of keyboard focus 2021-05-27 21:06:33 +02:00
Lurkars b586ef79ad audio player volume improvements 2021-05-27 21:02:58 +02:00
Thomas Basler a1fd55444a Merge remote-tracking branch 'upstream/develop' into develop 2021-05-26 22:22:53 +02:00
David Négrier 474323b95f
Merge pull request #933 from ClementVieilly75/SoundInMapScript
Sound in map script
2021-05-26 16:25:50 +02:00
David Négrier 9aed9713c8 Referencing sound test in index.html 2021-05-26 16:22:58 +02:00
David Négrier 769d9cf314 Added sound loading to changelog 2021-05-26 16:18:58 +02:00
David Négrier 870f16f9c6 Merge branch 'develop' of github.com:thecodingmachine/workadventure into SoundInMapScript 2021-05-26 16:15:33 +02:00
David Négrier 54e300443b Fixing Typing 2021-05-26 16:11:22 +02:00
David Négrier fac6574cb5 Removing console.log and unused files 2021-05-26 16:08:43 +02:00
David Négrier 1523758106
Merge pull request #1038 from thecodingmachine/dependabot/npm_and_yarn/pusher/lodash-4.17.21
Bump lodash from 4.17.20 to 4.17.21 in /pusher
2021-05-26 15:50:34 +02:00
David Négrier 701710a2a1
Merge pull request #1037 from thecodingmachine/dependabot/npm_and_yarn/pusher/hosted-git-info-2.8.9
Bump hosted-git-info from 2.8.8 to 2.8.9 in /pusher
2021-05-26 15:50:17 +02:00
David Négrier 728c2ee092
Merge pull request #1026 from thecodingmachine/dependabot/npm_and_yarn/messages/hosted-git-info-2.8.9
Bump hosted-git-info from 2.8.8 to 2.8.9 in /messages
2021-05-26 15:49:57 +02:00
dependabot[bot] faff263b80
Bump hosted-git-info from 2.8.8 to 2.8.9 in /pusher
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-26 13:49:56 +00:00
David Négrier 62627ba1b0
Merge pull request #1025 from thecodingmachine/dependabot/npm_and_yarn/benchmark/hosted-git-info-2.8.9
Bump hosted-git-info from 2.8.8 to 2.8.9 in /benchmark
2021-05-26 15:49:42 +02:00
David Négrier a1022f768b
Merge pull request #1024 from thecodingmachine/dependabot/npm_and_yarn/uploader/hosted-git-info-2.8.9
Bump hosted-git-info from 2.8.8 to 2.8.9 in /uploader
2021-05-26 15:49:29 +02:00
David Négrier 1bf4475e1b
Merge pull request #1023 from thecodingmachine/dependabot/npm_and_yarn/maps/hosted-git-info-2.8.9
Bump hosted-git-info from 2.8.8 to 2.8.9 in /maps
2021-05-26 15:49:17 +02:00
David Négrier f67ca05147
Merge pull request #1020 from thecodingmachine/dependabot/npm_and_yarn/back/hosted-git-info-2.8.9
Bump hosted-git-info from 2.8.8 to 2.8.9 in /back
2021-05-26 15:49:03 +02:00
David Négrier 796aaf82ce
Merge pull request #1060 from thecodingmachine/media_manager_store
Switching MediaManager to using a Svelte store
2021-05-26 15:25:15 +02:00
David Négrier 6d15921674 Fixing screen-sharing button not hidden anymore when hovering button 2021-05-26 12:30:56 +02:00
David Négrier 4f1cab5afe Fixing comments 2021-05-26 12:19:58 +02:00
David Négrier 4c4f310b79 The share screen button is now displayed only when screen sharing makes sense.
Also, fixed the button not aligned bug
2021-05-26 12:12:47 +02:00
David Négrier dd428bc1e1 Migrating screen sharing to using a store 2021-05-26 12:12:47 +02:00
David Négrier d32df13f1b Camera now show up when someone is moving and hides 5 seconds after we stop moving.
Also, added an animation to show/hide the webcam.
2021-05-26 12:12:46 +02:00
David Négrier 8af8ccd54b Migrating MediaManager game part to Svelte store 2021-05-26 12:12:18 +02:00
David Négrier 28d78a7988 Switching MediaManager to using a Svelte store
This allows cleaner and more expressive code, especially regarding whether the webcam should be on or off.
2021-05-26 12:11:16 +02:00
David Négrier 4f4d2532b7
Merge pull request #1082 from thecodingmachine/disabling_physics_optim
Moving Physics optim to DirtyScene
2021-05-26 12:08:57 +02:00
David Négrier bc19cbd525 Moving Physics optim to DirtyScene
The Physics engine is now disabled only if no sprites are moving (if they have no velocity).
Also, if a sprite is moving (if it has a velocity), the dirty state is set.
2021-05-26 12:00:27 +02:00
Kharhamel 177f0eb053
Merge pull request #863 from thecodingmachine/emote
FEATURE: added the possibility to play emotes
2021-05-26 10:26:13 +02:00
kharhamel 595c5ca64d now use custom emotes with tweens instead of transistions 2021-05-25 16:37:24 +02:00
David Négrier 2814a95a74
Merge pull request #1081 from thecodingmachine/disable_tsx_for_maps
Removing parsing of TSX files in "maps" container
2021-05-25 10:51:52 +02:00
David Négrier 4d18e0ceb4 Removing parsing of TSX files in "maps" container
The TSX extension is used by Typescript (for JSX like files) but ALSO by Tiled (for tilesets).
We don't need the Typescript TSX files so this PR is preventing Typescript from parsing those files in the "maps" container.
2021-05-25 10:43:01 +02:00
DESKTOP-FMM8UI0\CLV 0c3b9ccfbf Merge branch 'develop' of https://github.com/thecodingmachine/workadventure into SoundInMapScript
# Conflicts:
#	front/src/Api/IframeListener.ts
#	front/src/Phaser/Game/GameScene.ts
#	front/src/iframe_api.ts
#	maps/Tuto/scriptTuto.js
#	maps/Village/Village.json
2021-05-21 17:45:26 +02:00
kharhamel d93b30f982 improved radial menu 2021-05-19 18:11:51 +02:00
kharhamel 35b37a6a88 Added a radial menu to run emotes 2021-05-19 15:17:50 +02:00
kharhamel a1d52b4265 FEATURE: added the possibility toplay emotes 2021-05-19 15:17:03 +02:00
Kharhamel b57a9957a3
Merge pull request #1058 from thecodingmachine/fixAxiosErrors
FIX: rejected map axios promises are now catched
2021-05-18 12:12:49 +02:00
kharhamel 20ec609535 FIX: rejected map axios promises are now catched 2021-05-18 11:45:07 +02:00
David Négrier 2ea731beeb
Merge pull request #1057 from thecodingmachine/physics_flag
Making sure Physics is not enabled several times
2021-05-18 10:26:32 +02:00
David Négrier c9eb5691b5
Merge pull request #1045 from thecodingmachine/svelte
Installing Svelte in front container
2021-05-18 10:25:54 +02:00
David Négrier 4f10dd491c
Merge pull request #1056 from thecodingmachine/dirty_on_resize
Set a global dirty flag on resize
2021-05-18 09:45:51 +02:00
David Négrier 6128f1e431 Making sure Physics is not enabled several times
As part of an energy saving measure, we started disabling physics when the character is not moving and enabling physics again only when the character moves.
However, we enabled Physics on each frame the characeter was moving.
As a result, the Physics system would run several times, slowly slowing the computer down.

This fixes this issue by adding a flag to only enable Physics once.
2021-05-18 09:42:01 +02:00
David Négrier 24dfa2703d Set a global dirty flag on resize
This adds a global "Dirty" flag at the Game level and sets it each time the ScaleManager is modified.
This fixes a bug where the game was not redrawn when a CoWebsite was opening/closing.
2021-05-18 09:20:38 +02:00
David Négrier 54e9e5656b Commenting menu display (for now) 2021-05-17 16:50:35 +02:00
David Négrier 00dd5a8c84 Fixing Yarn 2021-05-17 16:45:52 +02:00
David Négrier 7cc1e5b2c6 Moving styles out of the "dist/" directory 2021-05-17 16:41:40 +02:00
David Négrier 79935593e2 Adding fork-ts-checker-webpack-plugin
This allows offloading type checking to another process and saves ~1-2 seconds for each build.
Also, we can integrate ESLint into the build pipeline and this is dope!
2021-05-17 16:41:38 +02:00
David Négrier 6e7f8507b1 Removing custom stats 2021-05-17 16:41:10 +02:00
David Négrier 849e68ece2 Optimizing build time + inline small files into CSS 2021-05-17 16:41:10 +02:00
David Négrier db40681be7 Code cleanup 2021-05-17 16:41:10 +02:00
David Négrier 9c4c6f2d53 Fixing Jasmine tests 2021-05-17 16:41:10 +02:00
David Négrier 5cb58d98a0 Adding correct SCSS file integration with Svelte 2021-05-17 16:41:09 +02:00
David Négrier 1885ea42a4 First working example with Svelte (the menu icon shows up on entering the game) 2021-05-17 16:39:56 +02:00
David Négrier 62cc1f73ca Tryig to fix webpack for Svelte 2021-05-17 16:39:56 +02:00
David Négrier 9bc79c3ed3 Adding Svelte to the project 2021-05-17 16:39:55 +02:00
Kharhamel 867f783d5e
Merge pull request #1054 from thecodingmachine/fixWebpackConfig
FIX: webpack config NodePolyfillPlugin
2021-05-17 16:33:04 +02:00
kharhamel f2dca82642 FIX: webpack config NodePolyfillPlugin 2021-05-17 16:30:19 +02:00
Kharhamel cfc156d022
Merge pull request #1053 from thecodingmachine/fixWebpackConfig
FEATURE: we now allow a global zoom level of 1.5
2021-05-17 16:17:07 +02:00
kharhamel a66d42e158 FEATURE: we now allow a global zoom level of 1.5 2021-05-17 16:11:38 +02:00
Kharhamel a6786c7494
Merge pull request #1052 from thecodingmachine/fixWebpackConfig
FEATURE: added new env variables
2021-05-17 15:12:12 +02:00
kharhamel a23e72454d FEATURE: added the env variable DISABLE_DIRTY_CHECKS 2021-05-17 14:47:34 +02:00
Kharhamel 99cc1b488f
Merge pull request #1051 from thecodingmachine/fixWebpackConfig
FIX: fixed an error in webpack config
2021-05-17 13:35:57 +02:00
kharhamel 1466d7481c FIX: fixed an error in webpack config 2021-05-17 12:20:07 +02:00
David Négrier fe573893a1
Merge pull request #1039 from thecodingmachine/importsNotUsedAsValues
Setting "importsNotUsedAsValues": "error"
2021-05-13 19:43:34 +02:00
David Négrier 8aeaf292b3
Merge pull request #1043 from thecodingmachine/webpack_typescript_config
Switching the Webpack configuration file to Typescript
2021-05-12 13:42:37 +02:00
David Négrier 4fcbc146ca Switching the Webpack configuration file to Typescript
This switches the Webpack config file from JS to Typescript.
2021-05-12 13:38:32 +02:00
David Négrier 9bf34a5117
Merge pull request #1040 from thecodingmachine/webpack5
Upgrading all dependencies in front
2021-05-12 11:55:10 +02:00
David Négrier 06058cfc24 Upgrading Typescript target from ES2015 to ES2017. 2021-05-12 11:45:01 +02:00
David Négrier 664a5b6b91 Upgrading ESLint (and ignoring a bunch of interesting rules) 2021-05-12 11:44:41 +02:00
David Négrier f57c01dee8 Refactoring Webpack files to remove prod file. The prod file is now inferred from the NODE_ENV variable. 2021-05-12 11:28:21 +02:00
David Négrier 8c1e01566a Upgrading all dependencies in front
Upgrading to Webpack 5, Typescript 4, ...
2021-05-12 10:35:14 +02:00
David Négrier 4d4f845b9e Setting "importsNotUsedAsValues": "error"
Turning the "importsNotUsedAsValues" TS config value to "error".
This will require us to use `import type` instead of `import` when we are importing a value that is only used as a type (and therefore that is dropped by the Typescript compiler).

Why this change?
This is a requirement to be able to use Svelte in the future. See https://github.com/sveltejs/svelte-preprocess/issues/206#issuecomment-663193798
2021-05-12 09:13:25 +02:00
dependabot[bot] aff912da55
Bump lodash from 4.17.20 to 4.17.21 in /pusher
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] <support@github.com>
2021-05-11 23:45:14 +00:00
David Négrier b56e4b5674
Merge pull request #1036 from tabascoeye/patch-1
turning noise suppresion back on
2021-05-11 18:14:17 +02:00
TabascoEye 627db30410
turning noise suppresion back on
turning AGC off was a good idea, disabling noise suppresion with it was not.
=> should all end up in the "settings" menu in the end
2021-05-11 17:38:28 +02:00
David Négrier d2b122efe5
Merge pull request #1035 from thecodingmachine/improveDirtyScene
FIX: trackDirtyAnims now listen to more generic events
2021-05-11 17:08:29 +02:00
kharhamel 4ec5ad9e33 FIX: trackDirtyAnims now listen to more generic events 2021-05-11 16:44:31 +02:00
David Négrier 0c279750be Merge branch 'master' of github.com:thecodingmachine/workadventure into develop
# Conflicts:
#	front/src/Phaser/Game/GameScene.ts
2021-05-11 16:43:34 +02:00
David Négrier 5674b99734
Merge pull request #1034 from thecodingmachine/close_game_webcam_in_jitsi
Close game webcam when in Jitsi
2021-05-11 15:56:22 +02:00
David Négrier ad39b43df3 Closing game webcame in Jitsi
When stepping in Jitsi, the game webcam (from mediaManager) was not shut down.
And when enabling/disabling the webcam in Jitsi, the webcam in mediaManager was also
enabled/disabled. This PR fixes those issues.

It also fixes a race condition when closing a Jitsi where the mic/cam would be enabled at the same time.
2021-05-11 14:52:51 +02:00
David Négrier 03a0402b3e
Merge pull request #1033 from thecodingmachine/use_visibility_change_api
Refactoring code to use the "visibilitychange" event
2021-05-11 14:50:22 +02:00
Kharhamel 78d4985d10
Merge pull request #1028 from thecodingmachine/fixOnMapExit
FIX: triggering a map transition now ignores other map transitions for 500ms
2021-05-11 14:21:06 +02:00
kharhamel f044b3d249 FIX: triggering a map transition now ignores other map transitions for 500ms 2021-05-11 11:05:05 +02:00
David Négrier 23bf78a026 Refactoring code to use the "visibilitychange" event
Using the "visiblitychange" event instead of relying on a "trick" related to RAF being disabled when a window is not open allows us to have cleaner code.
Bonus: the recursive call to "setTimeout" is gone, so the stacktrace growing indefinitely is gone too.
This should make the application a bit more stable.
2021-05-11 10:56:50 +02:00
David Négrier 0229f09ec6
Merge pull request #1032 from thecodingmachine/CheryPickDicussionCircle
Improve focus/blur discussion circle
2021-05-11 10:17:15 +02:00
Gregoire Parant e50aad0ea0 Add WA logo 2021-05-11 10:13:50 +02:00
Gregoire Parant 52b1c6733b Notification & Camera
- Notification when user is first and not focus on the tab
- Camera focus when user is in discussion circle and back on tab with previous config camera settings
- Camera stay blur if user is in discussion circle and not back on the tab

# Conflicts:
#	front/src/WebRtc/MediaManager.ts
2021-05-11 10:13:38 +02:00
David Négrier 5f6d9e060c
Merge pull request #1027 from thecodingmachine/fix_resize_helpcamera
Fixing "camera popup" always display on resize
2021-05-11 10:05:52 +02:00
grégoire parant 0fd743bcac
HotFix sound meter (#1029) 2021-05-10 20:49:17 +02:00
grégoire parant bd4cf5d7f7
Fix error context sound meter (#1009) 2021-05-10 19:55:43 +02:00
David Négrier 0411d5e493 Fixing "camera popup" always display on resize
This fixes a bug where the "camera popup" window was always displayed when the screen was resized.
2021-05-10 19:05:01 +02:00
David Négrier 58482f8ae6 Improving Changelog 2021-05-10 19:01:29 +02:00
dependabot[bot] 003bdf18cb
Bump hosted-git-info from 2.8.8 to 2.8.9 in /messages
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-10 16:58:41 +00:00
dependabot[bot] e0d496c7b7
Bump hosted-git-info from 2.8.8 to 2.8.9 in /benchmark
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-10 16:57:51 +00:00
dependabot[bot] 50ee2e9810
Bump hosted-git-info from 2.8.8 to 2.8.9 in /uploader
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-10 16:57:50 +00:00
David Négrier a95d592659
Merge pull request #1004 from thecodingmachine/dependabot/npm_and_yarn/back/lodash-4.17.21
Bump lodash from 4.17.20 to 4.17.21 in /back
2021-05-10 18:57:46 +02:00
dependabot[bot] 25d1e575ef
Bump hosted-git-info from 2.8.8 to 2.8.9 in /maps
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-10 16:57:45 +00:00
David Négrier 4606173ed1
Merge pull request #1003 from thecodingmachine/dependabot/npm_and_yarn/messages/lodash-4.17.21
Bump lodash from 4.17.20 to 4.17.21 in /messages
2021-05-10 18:57:30 +02:00
David Négrier 954b87db41
Merge pull request #1002 from thecodingmachine/dependabot/npm_and_yarn/maps/lodash-4.17.21
Bump lodash from 4.17.20 to 4.17.21 in /maps
2021-05-10 18:57:16 +02:00
David Négrier cd8501d80e
Merge pull request #1001 from thecodingmachine/dependabot/npm_and_yarn/uploader/lodash-4.17.21
Bump lodash from 4.17.20 to 4.17.21 in /uploader
2021-05-10 18:57:04 +02:00
dependabot[bot] 3b6daa99c0
Bump hosted-git-info from 2.8.8 to 2.8.9 in /back
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-10 11:50:12 +00:00
Kharhamel 6e868408ed
Merge pull request #1018 from thecodingmachine/fixStagingBuild
added back automatic deploy of staging 3
2021-05-10 12:45:25 +02:00
kharhamel d1f1c8f470 added back automatic deploy of staging 3 2021-05-10 12:44:35 +02:00
David Négrier d2bab4e7ef
Merge pull request #1017 from thecodingmachine/change_xxxplayercontrol_name
Renaming restorePlayerControls/disablePlayerControls
2021-05-10 12:35:34 +02:00
Kharhamel dfc57d0529
Merge pull request #1016 from thecodingmachine/fixStagingBuild
added back automatic deploy of staging  2
2021-05-10 12:29:11 +02:00
kharhamel de1768b7bb added back automatic deploy of staging 2 2021-05-10 12:20:46 +02:00
David Négrier c025d1798b Renaming restorePlayerControls/disablePlayerControls
Putting "controls" in the plural form:

- restorePlayerControl => restorePlayerControls
- disablePlayerControl => disablePlayerControls
2021-05-10 12:18:06 +02:00
David Négrier 3a82481d70 Merge branch 'master' of github.com:thecodingmachine/workadventure into develop 2021-05-10 12:10:57 +02:00
David Négrier c1da898c59
Merge pull request #1015 from thecodingmachine/markdown_doc
Splitting scripting API doc in 2
2021-05-10 12:09:20 +02:00
David Négrier 293c57568e 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
2021-05-10 12:08:52 +02:00
Kharhamel 8cb32c34b5
Merge pull request #1014 from thecodingmachine/fixStagingBuild
added back automatic deploy of staging
2021-05-10 12:03:23 +02:00
kharhamel 9a8b10bbf5 added back automatic deploy of staging 2021-05-10 11:56:08 +02:00
David Négrier 945ff446a9
Merge pull request #1012 from thecodingmachine/markdown_doc
Adding Markdown documentation relative to scripting
2021-05-10 10:56:43 +02:00
David Négrier e0ac8abd51
Merge pull request #1011 from thecodingmachine/markdown_doc
Adding Markdown documentation relative to scripting
2021-05-10 10:54:16 +02:00
David Négrier bc88a7d3ed Adding Markdown documentation relative to scripting 2021-05-10 10:47:55 +02:00
David Négrier 44eb25e9f6
Merge pull request #1006 from jonnytest1/typed-api-events
Typed api events
2021-05-10 09:13:49 +02:00
jonny 91148035ec polyfill generic message event 2021-05-09 21:46:40 +02:00
jonny cf06f29ef8 fixed cherry pick conflicts 2021-05-09 21:38:11 +02:00
jonny 8da5bf9f8e typed iframe api events
# Conflicts:
#	front/src/Api/IframeListener.ts
#	front/src/iframe_api.ts
2021-05-09 21:36:48 +02:00
DESKTOP-FMM8UI0\CLV e655edd9bd export class Popup and Soud of Iframe Api
let become const in SoundManager
2021-05-07 17:03:07 +02:00
dependabot[bot] b141da1475
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] <support@github.com>
2021-05-07 13:45:33 +00:00
dependabot[bot] 543397efe4
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] <support@github.com>
2021-05-07 13:45:29 +00:00
dependabot[bot] 9c620de649
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] <support@github.com>
2021-05-07 13:45:25 +00:00
dependabot[bot] 3a00ecab8f
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] <support@github.com>
2021-05-07 13:44:51 +00:00
David Négrier 5605e63e5f
Merge pull request #998 from thecodingmachine/skiprender2
Skip "render" if nothing changed on screen (2)
2021-05-07 15:44:08 +02:00
Gregoire Parant 62a6eabc88 Merge branch 'master' into develop 2021-05-07 00:07:43 +02:00
grégoire parant 0e32238505
HotFix custom WOKA (#999) 2021-05-06 19:58:08 +02:00
David Négrier 66490c9083 Adding test map to test energy consumption 2021-05-06 16:31:39 +02:00
David Négrier 6b4d064f19 Merge branch 'develop' of github.com:thecodingmachine/workadventure into skiprender2
# Conflicts:
#	front/src/Phaser/Game/GameScene.ts
#	front/src/index.ts
2021-05-06 16:25:13 +02:00
David Négrier 189dba2e21 Fixing memory leak when switching scenes 2021-05-06 15:38:24 +02:00
David Négrier 3b5f105daf Setting the dirty state automatically when there is an animation frame 2021-05-06 15:38:22 +02:00
David Négrier 6d3cbc573c Instruct systems with 2 GPUs to use the low power GPU (to save battery) 2021-05-06 15:36:49 +02:00
David Négrier 0c5e5ef578 Skip "render" if nothing changed on screen
For each requested animation frame (RAF) in Phaser, Phaser calls the "update" method, then the "render" method of each scenes.
The "render" method takes some time (and energy) to perform the rendering.

The fact is we probably don't need to call "render" if nothing changed on the screen (which happens most of the frames in a typical WorkAdventure game).

This commit is therefore overloading the "Game" class of Phaser to add a "dirty" flag.

Scenes can now add a "isDirty()" method. If all displayed scenes are pristine (not dirty), Phaser will skip rendering the frame altogether.

This saves "a lot" of energy, resulting in laptops that are not overheating when using WorkAdventure \o/
2021-05-06 15:36:45 +02:00
David Négrier 271300aa8d
Merge pull request #982 from jonnytest1/baseUrlFix
fixed url cannot be relative
2021-05-06 15:09:13 +02:00
Gregoire Parant 1440faf825 Merge branch 'master' into develop 2021-05-06 00:57:55 +02:00
grégoire parant 46978d26f9
Add entry map village WorkAdventure (#997) 2021-05-06 00:53:04 +02:00
jonny a24ca078e6 use iframe url if no script
# Conflicts:
#	front/src/Api/IframeListener.ts
2021-05-05 19:15:32 +02:00
David Négrier fea1de36a4
Merge pull request #974 from tabascoeye/patch-1
allow numbers in nickname again
2021-05-05 18:44:01 +02:00
David Négrier f085393730
Merge pull request #992 from tabascoeye/patch-2
getting rid of special char in filename
2021-05-05 18:34:46 +02:00
David Négrier 77d14ee7ce
Merge pull request #994 from thecodingmachine/resolution
Improving centering of HTML elements in setup scenes
2021-05-05 18:33:49 +02:00
David Négrier 989528f729 Updating changelog 2021-05-05 17:14:28 +02:00
David Négrier 3751b0e2bc Removing RESOLUTION and ZOOM_LEVEL settings: they are no more needed or supported 2021-05-05 17:11:03 +02:00
David Négrier 7ae66a63a4 Refactoring centering of DOM elements 2021-05-05 17:10:39 +02:00
David Négrier 9c4a0245a3
Merge pull request #924 from thecodingmachine/resolution
Improving mobile rendering / adding zoom / pinch
2021-05-05 16:21:13 +02:00
David Négrier c1be97e366 Adding test cases for mobile 2021-05-05 16:18:37 +02:00
David Négrier 04448c3c50 Fixing button position in webcam setting page 2021-05-05 15:46:02 +02:00
David Négrier cd2873e9d3 Fixing CI 2021-05-05 13:14:00 +02:00
David Négrier 4b89e08ea6 Reverting hard coded environment variable 2021-05-05 12:17:06 +02:00
David Négrier bede7abdd8 Removing mousewheel to up down plugin 2021-05-05 12:15:13 +02:00
David Négrier 10bd073b7d Fixing center computation of popup 2021-05-05 12:12:56 +02:00
David Négrier 7d2cc66f11 Fixing pointer-events interaction preventing virtual joystick from working 2021-05-05 11:56:24 +02:00
David Négrier 82073098e0 Merge branch 'develop' of github.com:thecodingmachine/workadventure into resolution 2021-05-05 11:01:11 +02:00
David Négrier a6ad1674e3 Fixing broken resize 2021-05-05 09:51:04 +02:00
David Négrier f66e69cb75 Improving pinch (virtual joystick stops when pinch begins) 2021-05-05 09:35:24 +02:00
grégoire parant 4d0220e118
Merge pull request #990 from thecodingmachine/develop
Release 04/05

- WorkAdventure Village
- Fix loader
- Create sound meter
2021-05-05 02:05:07 +02:00
grégoire parant 71eb3f3b69
Improvement feature circle discussion (#977)
* Improvment circle discussion
 - Change to lissen start event of WebRTC connection

* Update help allow navigator and waring message
 - Show warning message.
 - Use help camera allow setting to show modal and help user.
 - Change feature to show the modal only when user have need the information on allow navigator access

* Create soud for video discussion
2021-05-05 01:49:04 +02:00
Gregoire Parant 83159a121f Revert logo loading and fix it 2021-05-04 15:47:45 +02:00
Gregoire Parant c8692a08ce Revert "Fix loader logo WA (#991)"
This reverts commit fa3ffe4d7a.
2021-05-04 15:15:23 +02:00
grégoire parant fa3ffe4d7a
Fix loader logo WA (#991) 2021-05-04 14:28:30 +02:00
David Négrier 59b391e983 Prevent WA scale manager from zooming too much 2021-05-04 14:08:40 +02:00
TabascoEye 8d45338044
re-upload without accent in filename 2021-05-04 13:50:07 +02:00
TabascoEye 2b30bea3e0
Delete sol_intérieur.png 2021-05-04 13:49:32 +02:00
TabascoEye ec02b11b7f
remove accent from filename 2021-05-04 13:48:20 +02:00
grégoire parant 622e0c6130
Add WA logo in village map (#989) 2021-05-04 12:39:00 +02:00
David Négrier 613ff5d463 Adding zoom out limit 2021-05-04 12:09:00 +02:00
David Négrier 85efe208b3 Changing default map for docker-compose single-domain 2021-05-04 11:35:55 +02:00
David Négrier 04d3cf8593 Adding HdpiManager to start and scale from a default resolution that is correct by default for the game.
Fixing VirtualJoystick on resize.
2021-05-04 11:35:33 +02:00
jonnytest1 5069099000
fixed typing in chat still causes character to move (#965) 2021-05-03 20:26:42 +02:00
grégoire parant 95ec5dc3f6
Merge pull request #917 from ClementVieilly75/MapWA_Feature
Map village with new WA Office and features presented
2021-05-03 20:12:33 +02:00
jonnytest1 0a5dffd034
Update ScriptUtils.ts 2021-05-03 16:11:16 +02:00
jonny d674ac9e0c fixed url cannot be relative 2021-05-01 17:43:31 +02:00
David Négrier 4c55b5657f
Merge pull request #973 from thecodingmachine/better_error_message
Improving error messages
2021-04-30 13:31:04 +02:00
TabascoEye 7592a71bd5
remove test case with numbers being invalid in nickname 2021-04-30 10:58:01 +02:00
TabascoEye 2b2c60cbe3
allow numbers in nickname again
closes #972
2021-04-30 10:51:23 +02:00
David Négrier 3c9d477c06 Improving error messages
Trying to put more expressive and helpful error messages for the end user.
2021-04-30 09:33:18 +02:00
grégoire parant 1c20b33d4e
Merge pull request #971 from thecodingmachine/develop
Add error message (#970)
2021-04-30 00:15:40 +02:00
grégoire parant 925545d74f
Add error message (#970)
- Error link not found
 - Error user was banned
 - Error access dinied on the world
2021-04-29 23:47:30 +02:00
Kharhamel d1ef4a7342
Merge pull request #969 from thecodingmachine/develop
Deployment bis 29/04/2021
2021-04-29 18:47:51 +02:00
Kharhamel 7cd7d22e8b
Merge pull request #968 from thecodingmachine/releaseBuild
FIX: now used a slugified tag for prod deployment
2021-04-29 18:46:49 +02:00
kharhamel 0af3657acb FIX: now used a slugified tag for prod deployment 2021-04-29 18:44:46 +02:00
Kharhamel 0b749a4cab
Merge pull request #967 from thecodingmachine/develop
Déployment 29/04/2021
2021-04-29 18:32:29 +02:00
Kharhamel b4f2b005e1
Merge pull request #963 from thecodingmachine/releaseBuild
FIX: fixed the deploy workflow to also build images on new releases
2021-04-29 18:20:59 +02:00
kharhamel 7bd524ba55 FIX: fixed the deploy workflow to also build images on new releases 2021-04-29 18:11:24 +02:00
Kharhamel 746f1029a8
Merge pull request #687 from malteriechmann/patch-1
Run containers in the background using detached mode
2021-04-29 10:39:47 +02:00
Kharhamel a984151912
Merge pull request #904 from thecodingmachine/improvetestcases
Improving test cases
2021-04-29 10:37:08 +02:00
kharhamel fe27169745 solved conflict with develop 2021-04-29 10:31:16 +02:00
Kharhamel 398326b3aa
Merge pull request #959 from thecodingmachine/dependabot/npm_and_yarn/front/ssri-6.0.2
Bump ssri from 6.0.1 to 6.0.2 in /front
2021-04-29 10:18:33 +02:00
David Négrier 2e4b03efff
Merge pull request #962 from thecodingmachine/bugfix/add_template_to_single_domain
Adding templater call to single domain startup
2021-04-29 09:45:16 +02:00
David Négrier d29dee3bd4 Adding templater call to single domain startup
The docker-compose.single-domain.yaml was missing a call to the templater script.
As a result, the first run would fail unless docker-compose.yaml was started before.

Closes #947
Closes #957
2021-04-29 09:42:15 +02:00
grégoire parant 19ae575b4f
HotFix style help modal (#960) 2021-04-29 01:49:09 +02:00
dependabot[bot] 1e42de9155
Bump ssri from 6.0.1 to 6.0.2 in /front
Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/npm/ssri/releases)
- [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md)
- [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-28 23:28:10 +00:00
grégoire parant 5c0b5ef74b
HotFix release v1.3.1 (#958)
- Update camera style support mobile
 - Fix admin console error
2021-04-29 01:26:09 +02:00
grégoire parant c2f62e2610
Merge pull request #956 from thecodingmachine/develop
Release 28/04 v1.3.1
2021-04-28 00:01:18 +02:00
Gregoire Parant 16397fe978 Merge branch 'master' into develop 2021-04-27 23:59:25 +02:00
grégoire parant 9b69910cb8
WIP: Update style for mobile (#942)
* Update style for mobile

 - Update style for mobile modale

* Fix overscroll

* Change css properties overflow

* Revert "Change css properties overflow"

This reverts commit 612fcc7e007fb03c7f72e5fa4b8a0604a184ae7d.

* rm image

* Update view mobile

* Fix CI
2021-04-27 23:58:33 +02:00
GRL78 57194fd0a1
Add maps for test (#915) 2021-04-27 23:45:28 +02:00
Kharhamel 94e564f135
Merge pull request #955 from thecodingmachine/fixCleanup
FIX: fixed cleanup for real this time
2021-04-27 18:26:12 +02:00
kharhamel 79701fe227 FIX: fixed cleanup for real this time 2021-04-27 18:18:20 +02:00
Kharhamel 76a21cafa0
Merge pull request #954 from thecodingmachine/restrictCD
FIX: fixed cleanup workflow
2021-04-27 17:28:03 +02:00
kharhamel 3ce5c2ec45 FIX: fixed cleanup workflow 2021-04-27 17:17:54 +02:00
Kharhamel c6ed2c5c57
Merge pull request #953 from thecodingmachine/restrictCD
FIX: fixed cleanup workflow
2021-04-27 17:03:45 +02:00
kharhamel 7a8765826e FIX: fixed cleanup workflow 2021-04-27 16:51:57 +02:00
Kharhamel c19201b636
Merge pull request #952 from thecodingmachine/restrictCD
edited CD domain in deeployer config
2021-04-27 16:37:37 +02:00
kharhamel ea009d912e edited CD domain in deeployer config 2021-04-27 16:30:35 +02:00
Kharhamel 998e051a45
Merge pull request #940 from thecodingmachine/restrictCD
FIX: the deploy action now only start when the label 'deploy' is applied to the PR
2021-04-27 15:49:15 +02:00
kharhamel 30cf078df5 FIX: the deploy action now only start when the label 'deploy' is applied to the PR 2021-04-26 18:33:03 +02:00
grégoire parant 4e09246c7f
Merge pull request #939 from thecodingmachine/develop
Release 26/04/2021
2021-04-26 13:42:27 +02:00
David Négrier ca628d9a90
Merge pull request #901 from thecodingmachine/text_display
Adding the ability to display "Text" objects from Tiled
2021-04-26 11:30:34 +02:00
David Négrier 08ca95b143 Fixing WorkWrap 2021-04-26 11:28:15 +02:00
David Négrier 22cb41dc29 Adding the ability to display "Text" objects from Tiled
I honestly don't believe text objects look good on map, and in real maps, I think text should be written on tiles.

However, for a variety of use cases (like in test maps in the /maps/test directory, it can be useful to be
able to display some text easily on a map.

This PR adds the ability to display this text.

Note: the "font" support cannot work correctly, as Tiled is listing fonts from the local
system, and those fonts are not available in a browser.
2021-04-26 11:28:13 +02:00
David Négrier e37ab7d8ad
Merge pull request #899 from thecodingmachine/Lurkars/map-group-layer-support
Map group layer support (2)
2021-04-26 11:26:21 +02:00
David Négrier 6e5fa2c514 Initiating CHANGELOG file 2021-04-26 11:21:36 +02:00
David Négrier 6815fe7a0a Added a new LayersIterator class
This class iterates recursively over layers, flattening groups.
This enables us to simplify the code when we iterate layers. We can remove all recursive function calls in the GameScene code (it is delegated to the LayersIterator)
2021-04-26 11:21:34 +02:00
Lurkars 66b90be0da remove redundancy 2021-04-26 11:20:28 +02:00
Lurkars 93b7b7bc91 removed redundancy, fix for startLayer 2021-04-26 11:20:28 +02:00
Lurkars 9b6be3466b support for group layer of Tiled (excludes 'start' layer) 2021-04-26 11:20:28 +02:00
grégoire parant f0d277af32
Nickname not centered in video-container (#935)
* Nickname not centered in video-container

#823
2021-04-24 15:45:58 +02:00
Gregoire Parant 364c1d3e98 Merge branch 'master' into develop 2021-04-24 10:39:49 +02:00
grégoire parant 61c8830e24
Merge pull request #934 from thecodingmachine/HotFixStyleMessgae
HotFix Fix style message displaying
2021-04-24 10:37:33 +02:00
Gregoire Parant 0c72378001 Fix style message displaying
#926
2021-04-24 10:36:53 +02:00
grégoire parant d9620c373f
Merge pull request #918 from thecodingmachine/newStartMobileScene
Mobile started scene
2021-04-23 19:51:45 +02:00
Gregoire Parant b934d3404f Fix feedback WorkAdventure team 2021-04-23 19:29:43 +02:00
DESKTOP-FMM8UI0\CLV b79d76fc2e parameter soundConfig is now optionnal
if user call mySound.play() the sound will be played with the base SoundConfig
2021-04-23 17:03:17 +02:00
DESKTOP-FMM8UI0\CLV f8bab9ce6b Map Village with all the tilesSets 2021-04-23 15:39:45 +02:00
DESKTOP-FMM8UI0\CLV f03f8076f3 Sound in Script Done
Fom script user can load, play and stop sound
2021-04-23 15:35:34 +02:00
David Négrier 4f4f499d47 Making alone mode more robust
This fixes a number of issues where the game was attempting to access a non existing connection (in alone mode)
2021-04-23 13:44:04 +02:00
Gregoire Parant f11e936143 Refactoring & fix feedback WorkAdventure 2021-04-23 03:59:14 +02:00
Gregoire Parant 8e52b8597c Merge branch 'develop' into newStartMobileScene
# Conflicts:
#	front/src/Phaser/Login/EnableCameraScene.ts
#	front/src/Phaser/Login/LoginScene.ts
#	front/src/Phaser/Login/SelectCharacterScene.ts
#	front/src/Phaser/Login/SelectCompanionScene.ts
2021-04-22 23:36:21 +02:00
Gregoire Parant d7f00b505a Update Companion Scene for mobile 2021-04-22 13:10:23 +02:00
Gregoire Parant 3697ddabfa Fix responsive Camera Settings 2021-04-22 11:47:59 +02:00
Gregoire Parant 3df32de83b Update camera and adapte for mobile 2021-04-22 11:26:35 +02:00
Kharhamel 1251cbdc76
Merge pull request #925 from thecodingmachine/touchZones
FIX: use phaser Zones instead of rectangles objects to create tap zones
2021-04-22 10:28:28 +02:00
Gregoire Parant 0a04f5d631 Finish select character scene and custom character scene 2021-04-22 02:29:13 +02:00
kharhamel c8ba3d8ab9 FIX: use phaser Zones instead of rectangles objects to create tap zones 2021-04-21 18:27:33 +02:00
kharhamel 6a2326c4b3 WIP: testing new resolution config 2021-04-21 18:04:00 +02:00
DESKTOP-FMM8UI0\CLV 517c0e86cb Can play Sound from a map script
add sound in the TutoMap
2021-04-21 16:47:19 +02:00
David Négrier f9f6abe7b3 Switching setTimeout to false 2021-04-21 10:37:20 +02:00
David Négrier 84bd5eff50 Bump Phaser version
This reverts commit f2c3d6f158.
Also, updates all dependencies to their latest allowed version.

# Conflicts:
#	front/package.json
#	front/yarn.lock
2021-04-21 10:35:38 +02:00
Gregoire Parant 78d888ffaf Update menu mobile
- Add mobile style share modal
- Add mobile style settings modal
- Add menu mobile style
2021-04-21 00:53:45 +02:00
Gregoire Parant 20e0a2553e Update cowebsite mobile style 2021-04-20 21:11:05 +02:00
Gregoire Parant 30c1825abd Update syle mobile
- update my video side
- update user video side
- update button video cam and microphone side
2021-04-20 19:54:37 +02:00
Gregoire Parant 09d5e0b689 Fix center select name modal 2021-04-20 18:58:19 +02:00
Gregoire Parant 2c862fe7e7 Refactor Login Scene 2021-04-20 18:49:42 +02:00
DESKTOP-FMM8UI0\CLV 676dbcc9d0 Map village with new WA Office and features presented 2021-04-20 16:56:48 +02:00
Kharhamel 5dc2f0ac47
Merge pull request #898 from thecodingmachine/touchZoom
FEATURE: add the ability to zoom in and out using touch screen
2021-04-20 14:51:08 +02:00
kharhamel 341b048d6c improved the visuals of the joystick 2021-04-20 14:26:52 +02:00
kharhamel 415d8f9466 the joystick is now visible only when pointer is down 2021-04-20 10:52:06 +02:00
Gregoire Parant 5e8951fdaa Merge branch 'master' into develop 2021-04-19 21:19:35 +02:00
grégoire parant d44e449e92
Merge pull request #916 from thecodingmachine/HotFixPerformance
HotFix performance
2021-04-19 21:17:26 +02:00
Gregoire Parant e7b5bb261d HotFix performance
- Change forceSetTimeOut to false and permit to freeze the scene.
 - Fix style sending audio message
 - Fix banned message from admin console
2021-04-19 20:19:40 +02:00
kharhamel 56287a2958 put the virtual joystick into the userInputManager and restricted it to touchscreens 2021-04-19 18:10:33 +02:00
David Négrier 06f6b3153c
Merge pull request #913 from ClementVieilly75/FTUEPopup
Ftue popup
2021-04-19 16:24:02 +02:00
Gregoire Parant f7daa6e3f5 Merge branch 'master' into develop 2021-04-19 16:05:31 +02:00
grégoire parant a43afbc124
Merge pull request #914 from thecodingmachine/hotfix-map-tuto
Hotfix redirect map tuto
2021-04-19 15:55:39 +02:00
Gregoire Parant dab74460bb Hotfix redirect map tuto 2021-04-19 15:45:46 +02:00
DESKTOP-FMM8UI0\CLV 7e6a8b477d Debug state of share Screen button 2021-04-19 15:16:56 +02:00
DESKTOP-FMM8UI0\CLV b9d9a78868 Link changed in Tutov3
Change position of cam and buttons share/cam/Mic
2021-04-19 14:42:49 +02:00
DESKTOP-FMM8UI0\CLV d31021c02d Replace share screen logo 2021-04-19 14:19:16 +02:00
David Négrier cb1dcb5786
Merge pull request #908 from ClementVieilly75/FTUEPopup
Unsubscribe to iframeEvents in CleanUpClosingScene
2021-04-19 11:24:43 +02:00
DESKTOP-FMM8UI0\CLV 5028a54422 Unsubscribe to iframeEvents in CleanUpClosingScene 2021-04-19 10:19:30 +02:00
David Négrier 94317be1ae Improving test cases
This PR improves test cases by adding a "index.html" webpage listing test maps
and by adding text in the map, explaining what needs to be tested.
2021-04-17 21:31:09 +02:00
David Négrier 110511461a Fixing WorkWrap 2021-04-17 18:55:39 +02:00
David Négrier 16daf7332a Adding the ability to display "Text" objects from Tiled
I honestly don't believe text objects look good on map, and in real maps, I think text should be written on tiles.

However, for a variety of use cases (like in test maps in the /maps/test directory, it can be useful to be
able to display some text easily on a map.

This PR adds the ability to display this text.

Note: the "font" support cannot work correctly, as Tiled is listing fonts from the local
system, and those fonts are not available in a browser.
2021-04-17 12:05:54 +02:00
Kharhamel afd2ea2d03
Merge pull request #897 from thecodingmachine/maxPerGroup
FEATURE: added the env variable MAX_PER_GROUP
2021-04-16 17:19:01 +02:00
kharhamel d7a74baa9d FEATURE: add the ability to zoom in and out using touch screen 2021-04-15 16:37:58 +02:00
kharhamel ce2c5e0cb5 FEATURE: added the env variable MAX_PER_GROUP 2021-04-15 15:50:51 +02:00
Gregoire Parant a42e873f64 Merge branch 'master' into develop 2021-04-14 20:11:41 +02:00
grégoire parant 085cf9045c
Merge pull request #891 from thecodingmachine/HotFixForm
Hot fix form
2021-04-14 20:10:31 +02:00
David Négrier 1a4f178728
Update front/src/Phaser/Menu/MenuScene.ts 2021-04-14 15:57:57 +02:00
Kharhamel 71898bff7d
Merge pull request #896 from thecodingmachine/fixXss
FIX: calling emitPlayGlobalMessage in pusher without the admin tag will throw an error
2021-04-14 12:21:04 +02:00
kharhamel 5ebb0c94e6 FIX: calling emitPlayGlobalMessage in pusher without the admin tag will throw an error 2021-04-14 11:56:54 +02:00
Kharhamel 3874b2bc2b
Merge pull request #688 from tabascoeye/patch-2
disable automatic gain control on microphone
2021-04-13 18:20:56 +02:00
Kharhamel faade46400
Merge pull request #894 from thecodingmachine/topVerticalMode
FIX: in vertical mode, the coWebSite now open from the top
2021-04-13 15:16:06 +02:00
Kharhamel 4bbfd4f12f
Merge pull request #893 from workadventure-xce/fix/first_login
Fix first login with empty local storage
2021-04-13 15:15:32 +02:00
Gregoire Parant ba8d3020eb Merge branch 'master' into HotFixForm 2021-04-13 12:33:04 +02:00
grégoire parant f5f4ee229b
Merge pull request #895 from thecodingmachine/hotFixKeyUp
HotFix
2021-04-13 12:32:18 +02:00
Gregoire Parant 4119f69879 HotFix
- Key up m when user write message
 - Size game share
2021-04-13 12:30:15 +02:00
kharhamel f82551016a FIX: in vertical mode, the coWebSite now open from the top 2021-04-13 11:34:14 +02:00
Kharhamel bbc42d2986
Merge pull request #873 from workadventure-xce/feature/mobile_support
Mobile/touch support
2021-04-13 09:49:47 +02:00
PizZaKatZe 633bdfcaff Always enable virtual joystick
Keeps 'toggle fullscreen' as a separate game setting.
2021-04-13 02:00:06 +02:00
PizZaKatZe 340caaff32 Make virtual joystick transparent 2021-04-13 02:00:05 +02:00
PizZaKatZe 9c9d262782 Make movement speed depend on joystick force 2021-04-13 02:00:05 +02:00
PizZaKatZe e713120434 Reposition joystick (thx @TabascoEye) 2021-04-13 02:00:04 +02:00
PizZaKatZe c3230bc2b3 Integrate virtual joystick 2021-04-13 02:00:03 +02:00
PizZaKatZe e75fb9a6a9 Add touch support to companion selection scene 2021-04-13 02:00:02 +02:00
PizZaKatZe 5462af0dc7 Fix first login with empty local storage
During first login on a new domain the local storage is empty. This led
to a TypeError and hence blank black screen.
2021-04-13 01:58:32 +02:00
PizZaKatZe edd4e9e95d Add touch support for Jitsi and website triggers 2021-04-13 00:23:40 +02:00
¯\_(ツ)_/¯ aab65298aa Add touch support to character customization screen 2021-04-13 00:23:40 +02:00
PizZaKatZe e807350279 Add touch input support to login scenes (thx @TabscoEye) 2021-04-13 00:23:37 +02:00
PizZaKatZe c7dcaec940 Make login text input field touch capable (thx @TabscoEye) 2021-04-13 00:19:06 +02:00
Gregoire Parant 270cdb5c82 Button "CREATE MAP" must redirect user on production server 2021-04-12 20:44:29 +02:00
Gregoire Parant 1693819b6a HotFix Share Form height 2021-04-12 20:23:00 +02:00
grégoire parant 2a6221afe2
Merge pull request #889 from thecodingmachine/HotFixStyle
HotFix style WorkAdventure
2021-04-12 19:30:06 +02:00
Gregoire Parant 6a08ca656f Add TODO 2021-04-12 18:26:36 +02:00
Gregoire Parant 4fc9a12b95 HotFix style WorkAdventure 2021-04-12 18:17:04 +02:00
Kharhamel 8cdf572685
Merge pull request #870 from joberthel/feature/player-companion
Added companion (pet) to player
2021-04-12 18:11:07 +02:00
Kharhamel 29d43d7776
Merge pull request #878 from thecodingmachine/localStorageGhost
FIX: improved the validation from localstorage for username and characterLayers
2021-04-12 14:56:51 +02:00
kharhamel 8e467f3e10 FIX: improved the validation from localstorage for username and characterLayers 2021-04-12 14:48:00 +02:00
David Négrier 5ad7787cd5
Merge pull request #887 from thecodingmachine/develop
Deploy 2021-04-11
2021-04-11 21:31:54 +02:00
David Négrier 34a0fc5014
Merge pull request #886 from thecodingmachine/npm_package_for_iframe_api_typings
Allowing loading HTTP local resources from a HTTPS endpoint.
2021-04-11 21:25:42 +02:00
David Négrier 3dd2a634a0 Allowing loading HTTP local resources from a HTTPS endpoint.
By default, maps are loaded in HTTPS if WorkAdventure is running in HTTPS, and in HTTP is WorkAdventure is running in HTTP.
Also, if WorkAdventure is running in HTTP and map loading fails, we try map loading in HTTPS (useful when we are working on WorkAdventure locally and want to load a map on a secure domain).

This commit adds the last combination: If WorkAdventure is running in HTTPS, and map loading fails in HTTPS **AND** if the map URL is targetting "localhost", "*.localhost" or "127.0.0.1", then we attempt to load the resource in HTTP.

Why?

"localhost" is considered secure context by modern browsers. So even if a page is loaded in HTTPS, it can load resources from any secure context (including localhost in HTTP).

This means that from "https://play.workadventu.re", I can now test a map running locally on my machine (served by a classic webserver without any certificate).
This change should make map testing easier, since map developers will not have to install the whole WorkAdventure project to test their map locally.
2021-04-11 14:56:03 +02:00
David Négrier 5beefcd274
Merge pull request #885 from thecodingmachine/npm_package_for_iframe_api_typings
Creating a dedicated package for iframe API typings
2021-04-11 11:38:50 +02:00
David Négrier 728fd4779c Dynamically fetching correct version and generating declarations only for npm lib 2021-04-11 11:32:56 +02:00
David Négrier 0f7ac7ba8b Added empty .npmignore to override .gitignore 2021-04-10 19:14:36 +02:00
David Négrier 6acf0ff047 Creating a dedicated package for iframe API typings
If users are willing to use Typescript to develop scripts for maps, they will need typings for the `WA` object.
This commit creates a new package (@workadventure/iframe-api-typings) that contains only the `iframe_api.d.ts` file.

The file is generated from the build of the front and isolated in this package.
This is necessary because the iframe_api.js file is supposed to always be loaded from WorkAdventure directly (and there is no @workadventure/iframe-api package and there will never be one)
2021-04-10 18:50:46 +02:00
Johannes Berthel 8d4e0c3e88 added companion compatibility with phaser 3.54.0 2021-04-09 18:30:30 +02:00
David Négrier a1f06ffbd5
Merge pull request #883 from ClementVieilly75/FTUEPopup
Ftue popup
2021-04-09 17:41:39 +02:00
David Négrier d80681c40b
Merge branch 'develop' into FTUEPopup 2021-04-09 17:40:26 +02:00
DESKTOP-FMM8UI0\CLV 8720354c87 exit Url changed : tcm/workadventure/floor0 2021-04-09 16:39:37 +02:00
DESKTOP-FMM8UI0\CLV 2c84d9a07d position of popups changed
clear log in gameScene
2021-04-09 16:34:01 +02:00
DESKTOP-FMM8UI0\CLV d52c983ab9 Merge branch 'FTUEPopup' of https://github.com/ClementVieilly75/workadventure into FTUEPopup 2021-04-09 14:35:20 +02:00
DESKTOP-FMM8UI0\CLV 46cc7b3b3b add pannels 2021-04-09 14:35:15 +02:00
Johannes Berthel 32784d6775 Merge branch 'develop' into feature/player-companion 2021-04-08 23:37:36 +02:00
David Négrier f77a02f0cd
Merge pull request #881 from thecodingmachine/develop
Deploy 2021-04-08
2021-04-08 21:52:25 +02:00
Johannes Berthel 73e515c236 don't show companion scene after first refresh 2021-04-08 18:42:05 +02:00
David Négrier fb6a529e4a
Merge pull request #879 from ClementVieilly75/FTUEPopup
map village + popUp go to page
2021-04-08 12:02:50 +02:00
David Négrier 34e89fa63e
Update maps/Village/scriptMapVillage.js 2021-04-08 12:02:14 +02:00
DESKTOP-FMM8UI0\CLV 0f4034854c Add closePopup function 2021-04-08 10:50:41 +02:00
DESKTOP-FMM8UI0\CLV eb66ab3fdd Supp arrow white 2021-04-08 10:17:52 +02:00
DESKTOP-FMM8UI0\CLV af69510bc8 Modif popup positions and add arrow 2021-04-08 09:41:53 +02:00
David Négrier aac8cc8d67
Merge pull request #848 from thecodingmachine/develop
Deploy 2021-03-29
2021-04-07 15:24:13 +02:00
DESKTOP-FMM8UI0\CLV 39074511a4 map village + popUp go to page 2021-04-07 13:06:30 +02:00
Johannes Berthel 2438470088 fixed rectangle resize issue 2021-04-06 20:31:08 +02:00
Johannes Berthel fb90111cdf refactored companion selection scene 2021-04-06 20:12:10 +02:00
Johannes Berthel 187e21eed9 load texture inside game scene instead inside of inside companion class 2021-04-06 19:10:18 +02:00
Johannes Berthel e5a196a42b implemented feedback 2021-04-06 18:54:45 +02:00
Johannes Berthel 7c6b73efdb don't show companion selection during first connexion flow 2021-04-06 18:36:46 +02:00
grégoire parant 575c1a9f23
Merge pull request #861 from joberthel/fix/use-selected-video-quality
Use selected video quality during webcam initialization
2021-04-06 15:08:03 +02:00
Johannes Berthel 6c512fb7cd fixed linting 2021-04-03 00:18:08 +02:00
Johannes Berthel 8c35860f2a show select companion scene after customize scene 2021-04-02 23:49:25 +02:00
Johannes Berthel 4aa082d83b Merge branch 'develop' into feature/player-companion 2021-04-02 23:40:30 +02:00
Johannes Berthel 3187520e7b companion behaviour fine tuning 2021-04-02 23:36:06 +02:00
Johannes Berthel 38c06ce8ff navigate from select character scene to select companion scene 2021-04-02 23:17:04 +02:00
Johannes Berthel 6ee4889773 added change companion button to menu 2021-04-02 23:13:03 +02:00
Johannes Berthel 52303c0bd6 added select companion scene 2021-04-02 23:00:51 +02:00
Johannes Berthel 4cfce15695 only remove listener if scene was not already destroyed 2021-04-02 21:29:45 +02:00
Johannes Berthel e4d324e5fa removed unused import 2021-04-02 21:26:42 +02:00
Johannes Berthel fc3a503bcf don't fail if companion texture is not found 2021-04-02 21:26:24 +02:00
Johannes Berthel c07079051a transmit companion to remote players 2021-04-02 21:21:11 +02:00
Johannes Berthel 2ad712807b add companion only on local player 2021-04-02 17:14:34 +02:00
Kharhamel 6e7b1f3ef6
Merge pull request #867 from thecodingmachine/roomEdition
FEATURE: editing a room in the admin trigger a refresh system
2021-04-02 15:29:39 +02:00
kharhamel 88cc15cd02 FEATURE: editing a room in the admin trigger a refresh system 2021-04-02 15:22:02 +02:00
Johannes Berthel 5a91e15580 add companion to remote player 2021-04-01 18:51:51 +02:00
David Négrier 8529037493
Merge pull request #864 from thecodingmachine/singledomain
Adding support for single domain deployments
2021-04-01 09:04:26 +02:00
David Négrier 9235809d53
Merge pull request #866 from thecodingmachine/dependabot/npm_and_yarn/pusher/y18n-3.2.2
Bump y18n from 3.2.1 to 3.2.2 in /pusher
2021-04-01 08:59:40 +02:00
Johannes Berthel 80a5d2e30e added random companion to player 2021-04-01 00:33:05 +02:00
dependabot[bot] f18562577e
Bump y18n from 3.2.1 to 3.2.2 in /pusher
Bumps [y18n](https://github.com/yargs/y18n) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-31 18:46:01 +00:00
Kharhamel 512c370f3f
Merge pull request #865 from thecodingmachine/cowebsiteControls
FEATURE: improved the fullscreen and close buttons
2021-03-31 18:45:49 +02:00
kharhamel a30923ceae FEATURE: improved the fullscreen and close buttons to be in the aside element 2021-03-31 18:39:51 +02:00
David Négrier adf2e60d54 Fixing issue with double slash in websocket URL 2021-03-31 17:50:27 +02:00
David Négrier e166c69b58 Fixing reading of the relative URL in RommConnection 2021-03-31 16:38:51 +02:00
David Négrier 651dfc63f4 Fixing TURN server config 2021-03-31 16:38:30 +02:00
David Négrier 11a1428c89 Fixing broken live-reload 2021-03-31 16:20:21 +02:00
David Négrier f2e64c8763 Fixing missing API_URL warning 2021-03-31 16:20:11 +02:00
David Négrier 3ef1f0dc7b [Breaking change] UPLOADER_URL and ADMIN_URL are now true URLs (and not only host name) and API_URL is replaced by PUSHER_URL
API_URL is still accepted for BC compatibility of the self-hosted deployments.

This will allow deploying on a single domain, using a reverse proxy that acts on the path.
This however means that the config needs to be changed for all WorkAdventure deployments.
2021-03-31 16:00:14 +02:00
David Négrier cd7a332b4c Improving error throwing and handling in pusher/admin/front 2021-03-31 15:49:01 +02:00
David Négrier 9bfd07f00c Merge branch 'develop' of github.com:thecodingmachine/workadventure into singledomain 2021-03-31 15:17:29 +02:00
Mewp 6f1fc08b82 Add a docker-compose file for hosting under a single domain. 2021-03-31 12:11:00 +02:00
David Négrier c2398efdc4
Merge pull request #860 from thecodingmachine/dependabot/npm_and_yarn/front/y18n-4.0.1
Bump y18n from 4.0.0 to 4.0.1 in /front
2021-03-31 09:25:14 +02:00
David Négrier 189e4313ea
Merge pull request #859 from thecodingmachine/dependabot/npm_and_yarn/back/y18n-3.2.2
Bump y18n from 3.2.1 to 3.2.2 in /back
2021-03-31 09:25:02 +02:00
David Négrier 9768055946
Merge pull request #858 from thecodingmachine/dependabot/npm_and_yarn/messages/y18n-3.2.2
Bump y18n from 3.2.1 to 3.2.2 in /messages
2021-03-31 09:24:51 +02:00
Johannes Berthel 441416f312 use frame rate setting for initialization 2021-03-30 22:38:44 +02:00
David Négrier dd0d1fa49f
Merge pull request #854 from thecodingmachine/loadhttpsmapsfromhttp
Allow loading https maps from http protocol
2021-03-30 17:57:38 +02:00
David Négrier a68cf38cdc
Merge pull request #856 from thecodingmachine/alonemode
Adding an "alone" mode
2021-03-30 17:56:19 +02:00
dependabot[bot] cff4c154ce
Bump y18n from 4.0.0 to 4.0.1 in /front
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-30 14:33:07 +00:00
dependabot[bot] b63ad7ceb7
Bump y18n from 3.2.1 to 3.2.2 in /back
Bumps [y18n](https://github.com/yargs/y18n) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-30 14:32:38 +00:00
dependabot[bot] 92439b5899
Bump y18n from 3.2.1 to 3.2.2 in /messages
Bumps [y18n](https://github.com/yargs/y18n) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-30 14:32:34 +00:00
David Négrier 02fb42b68a
Merge pull request #790 from thecodingmachine/iframe_api
Adding an API for inter-iframe communication
2021-03-30 16:31:30 +02:00
David Négrier 559e15ebb6 Adding an "alone" mode
In "alone" mode (or single-player mode), WorkAdventure does not connect to the server at all.
In order to enter the "alone" mode, you need to add "?alone=true" to the URL.

"alone" mode can be useful for tutorials (First Time User Experience) where you want to explain how WorkAdventure works without being disturbed by other users.
2021-03-30 16:08:49 +02:00
David Négrier b6edefbe4e Allow loading https maps from http protocol
In a development environment, we often run in HTTP.
The problem is that WorkAdventure will attempt to load maps using the HTTP protocol (even if the map is on a remote server that is available only in HTTPS).
This commit adds a "fallback". If we are in HTTP (so in a development environment) and if the map fails to load correctly, we will try again, but in HTTPS.

This allows development environment to load maps hosted on a HTTPS enabled server easily.
2021-03-28 18:35:01 +02:00
David Négrier ad4f8e892e
Merge pull request #852 from joberthel/fix-starting-position
use map tilewidth to calculate starting position instead of hardcoded value
2021-03-28 17:50:28 +02:00
David Négrier ccb80317ee Changing exit URL of Tuto map 2021-03-28 17:33:10 +02:00
David Négrier ee53d8f0b8 Hiding iframe in prod 2021-03-28 17:21:10 +02:00
David Négrier 8b90a14c39 Fix import 2021-03-28 17:07:00 +02:00
David Négrier aaaa192b71 Merge branch 'develop' of github.com:thecodingmachine/workadventure into iframe_api
# Conflicts:
#	front/dist/.gitignore
#	front/dist/index.tmpl.html
#	front/src/Phaser/Game/GameScene.ts
#	front/src/WebRtc/CoWebsiteManager.ts
2021-03-28 16:53:15 +02:00
David Négrier 07666f6ce2
Merge pull request #797 from ClementVieilly75/FTUEPopup
Popup early dev
2021-03-28 16:43:21 +02:00
David Négrier 98aa94bb12 Minor changes 2021-03-28 16:36:02 +02:00
Johannes Berthel 5375528d7c use map tilewidth instead of hardcoded values 2021-03-27 13:57:50 +01:00
DESKTOP-FMM8UI0\CLV 8764fe5de5 Popup openWebSite
Add possibility to open a website with a popup
3 cases :
Open page
GoTo Page
OpenCoWebsite
2021-03-25 17:12:53 +01:00
DESKTOP-FMM8UI0\CLV 7140637807 Map tuto version 3 by Jack O 2021-03-25 09:06:41 +01:00
DESKTOP-FMM8UI0\CLV cb1459de96 remove exitUrl 2021-03-24 11:00:24 +01:00
DESKTOP-FMM8UI0\CLV 7c7916df60 remove useless files and clean code in ScriptTuto.js 2021-03-24 10:58:30 +01:00
DESKTOP-FMM8UI0\CLV e05c25a857 replace let for const for variables non reassigned 2021-03-23 17:15:22 +01:00
DESKTOP-FMM8UI0\CLV 77e768e5f7 Add map Tuto v2 and scriptTuto.js 2021-03-23 16:00:24 +01:00
DESKTOP-FMM8UI0\CLV f437b6057c subProject maps/Tuto 2021-03-23 15:58:32 +01:00
DESKTOP-FMM8UI0\CLV 3ef3561b57 no message 2021-03-22 16:10:21 +01:00
DESKTOP-FMM8UI0\CLV 0ffbf8b4b7 Add Final popup to notify that the tuto is finished, some CSS on the popups and clean code 2021-03-22 16:09:04 +01:00
David Négrier 086b88b09a Merge branch 'develop' of github.com:thecodingmachine/workadventure into iframe_api 2021-03-12 18:02:02 +01:00
DESKTOP-FMM8UI0\CLV 662134498c Merge branch 'iframe_api' of https://github.com/thecodingmachine/workadventure into FTUEPopup
# Conflicts:
#	front/src/Phaser/Game/GameScene.ts
2021-03-12 17:06:42 +01:00
DESKTOP-FMM8UI0\CLV c5c8770a60 Add First Version of Tuto
PopUp
Player Control disable
Fake bubble displayed
2021-03-12 16:39:29 +01:00
DESKTOP-FMM8UI0\CLV fa4d917729 Resolve conflit with GameScene.ts 2021-03-11 16:03:39 +01:00
DESKTOP-FMM8UI0\CLV 6c21a31004 Update Map Tuto 2021-03-11 15:17:53 +01:00
DESKTOP-FMM8UI0\CLV 6441fa71d3 Adding placeHolder Popup tuto to Map2
need to cut player controller and simulate bobble
2021-03-11 10:58:48 +01:00
DESKTOP-FMM8UI0\CLV f9f618094d adding error log if name of square in Tile not matching with the param targetObject of OpenPopup in script.js 2021-03-10 17:22:39 +01:00
DESKTOP-FMM8UI0\CLV 8d0411e8a3 can manage position and width/height of a popUp using a square in Tiled 2021-03-10 09:23:45 +01:00
DESKTOP-FMM8UI0\CLV 5e4940dba6 Merge branch 'iframe_api' of https://github.com/thecodingmachine/workadventure into FTUEPopup
* 'iframe_api' of https://github.com/thecodingmachine/workadventure:
  Removing closeOnClick as it is not implemented
  Adding a Popup object with a close() method on it.
2021-03-10 09:00:47 +01:00
DESKTOP-FMM8UI0\CLV f7f8be24bc Set Position of the popUp with pos of an object in floorLayer object group 2021-03-10 08:57:49 +01:00
David Négrier 7fddcc28f1 Removing closeOnClick as it is not implemented 2021-03-09 18:57:25 +01:00
David Négrier bb8b222c22 Adding a Popup object with a close() method on it. 2021-03-09 18:51:30 +01:00
David Négrier 18464e4942 Adding button clicked handling 2021-03-09 18:05:07 +01:00
DESKTOP-FMM8UI0\CLV 4545de8af1 Merge branch 'iframe_api' of https://github.com/thecodingmachine/workadventure into FTUEPopup
* 'iframe_api' of https://github.com/thecodingmachine/workadventure:
  Adding button clicked handling

# Conflicts:
#	front/src/Phaser/Game/GameScene.ts
2021-03-09 17:12:28 +01:00
DESKTOP-FMM8UI0\CLV d29e0819f4 Get position of an object in Tile to set popUp Position 2021-03-09 17:07:14 +01:00
David Négrier 1e002f93ed Implementation of openPopup script method (WIP) 2021-03-09 16:21:14 +01:00
DESKTOP-FMM8UI0\CLV 70898a2f28 Merge branch 'iframe_api' of https://github.com/thecodingmachine/workadventure into FTUEPopup
* 'iframe_api' of https://github.com/thecodingmachine/workadventure:
  Implementation of openPopup script method (WIP)
  Adding the abaility to track users entering/leaving a zone in the script language.
  Adding the ability to register a single script using the "script" attribute at the map property level.
  Improving security: only iframes opened with "openWebsiteAllowApi" property are now able to send/receive messages.
  Adding ability to listen to user types chat messages using WA.onChatMessage
  Adding strong checks on messages exchanged using generic-type-guard
  Fixing eslint
  Adding an API for inter-iframe communication
2021-03-09 15:46:22 +01:00
David Négrier ed2ce68f37 Merge branch 'FTUEPopup' of github.com:ClementVieilly75/workadventure into iframe_api
# Conflicts:
#	front/dist/.gitignore
#	front/src/Phaser/Game/GameScene.ts
2021-03-09 15:35:51 +01:00
DESKTOP-FMM8UI0\CLV bbf5003e16 move font press start 2P from index.html to style.css 2021-03-09 14:21:11 +01:00
DESKTOP-FMM8UI0\CLV b175b7164d Merge branch 'develop' of https://github.com/thecodingmachine/workadventure into FTUEPopup
* 'develop' of https://github.com/thecodingmachine/workadventure:
  Trying to enable back connection on admin from develop, knowing that the develop certificate is broken. Fixing priority.
  Trying to enable back connection on admin from develop, knowing that the develop certificate is broken
  Revert "Adding back admin in develop branch CI"
  Adding back admin in develop branch CI
  Fixing GA tag not included in play domain
  FEATURE: better implementation of the admin global message
  Fix ci
  Update private access
  Allow URLs relative to map base in iframe / openWebsite

# Conflicts:
#	front/src/Phaser/Game/GameScene.ts
2021-03-09 13:57:05 +01:00
DESKTOP-FMM8UI0\CLV afac042706 supp debug log 2021-03-09 13:53:46 +01:00
David Négrier 2bef328d8a Adding the abaility to track users entering/leaving a zone in the script language. 2021-03-08 18:58:38 +01:00
DESKTOP-FMM8UI0\CLV 858bf0b384 Adding property tile "inGameConsoleMessage", open a popup when user walk on a tile with this property
Adding map "Tuto2", the FTUE map
2021-03-08 09:28:15 +01:00
David Négrier 6fbf165c91 Adding the ability to register a single script using the "script" attribute at the map property level. 2021-03-07 21:02:38 +01:00
David Négrier 7d67f55012 Improving security: only iframes opened with "openWebsiteAllowApi" property are now able to send/receive messages. 2021-03-06 16:00:07 +01:00
David Négrier e927e0fa16 Adding ability to listen to user types chat messages using WA.onChatMessage 2021-03-06 15:26:07 +01:00
David Négrier 5178dff108 Adding strong checks on messages exchanged using generic-type-guard 2021-03-05 16:50:54 +01:00
David Négrier 83fa23a82d Fixing eslint 2021-03-05 11:47:04 +01:00
David Négrier eb93a04341 Adding an API for inter-iframe communication
Adds a first version of an API to communicate between an iFrame opened by WorkAdventure and WorkAdventure itself.
The first API method is a method allowing to add messages in the chat, from the iFrame.

Comes with a test file.
2021-03-04 19:00:00 +01:00
TabascoEye 58b7d85bf3
bugfix and linting
* use 'const' on constraints which never change
* also re-enable constraints ater mic was re-enabled (after mute/unmute)
2021-01-30 02:24:36 +01:00
TabascoEye 31a0d08c76
disable automatic gain control on microphone
AGC really makes the soundqulity way worse than it could be.
Especially since it is so noticeable when entering a Jitsi where AGC is disabled (and suddenly some people sound much better).

In the long run, this should probably be configurable. On the other hand the setting changes the audio _going out_ from a user, so it might be hard for him to judge which settings are a good or a bad idea…
2021-01-30 02:13:03 +01:00
Malte Riechmann 69ff15ff71
Run containers in the background using detached mode 2021-01-29 21:45:01 +01:00
321 changed files with 18533 additions and 3863 deletions

View File

@ -10,6 +10,12 @@ START_ROOM_URL=/_/global/maps.workadventure.localhost/Floor0/floor0.json
# If you are using Coturn, this is the value of the "static-auth-secret" parameter in your coturn config file.
# Keep empty if you are sharing hard coded / clear text credentials.
TURN_STATIC_AUTH_SECRET=
DISABLE_NOTIFICATIONS=true
SKIP_RENDER_OPTIMIZATIONS=false
# The email address used by Let's encrypt to send renewal warnings (compulsory)
ACME_EMAIL=
MAX_PER_GROUP=4
MAX_USERNAME_LENGTH=8

View File

@ -1,164 +0,0 @@
name: Build, push and deploy Docker image
on:
- push
# Enables BuildKit
env:
DOCKER_BUILDKIT: 1
jobs:
build-front:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
# Create a slugified value of the branch
- uses: rlespinasse/github-slug-action@3.1.0
- name: "Build and push front image"
uses: docker/build-push-action@v1
with:
dockerfile: front/Dockerfile
path: ./
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: thecodingmachine/workadventure-front
tags: ${{ env.GITHUB_REF_SLUG }}
add_git_labels: true
build-back:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
# Create a slugified value of the branch
- uses: rlespinasse/github-slug-action@3.1.0
- name: "Build and push back image"
uses: docker/build-push-action@v1
with:
dockerfile: back/Dockerfile
path: ./
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: thecodingmachine/workadventure-back
tags: ${{ env.GITHUB_REF_SLUG }}
add_git_labels: true
build-pusher:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
# Create a slugified value of the branch
- uses: rlespinasse/github-slug-action@3.1.0
- name: "Build and push back image"
uses: docker/build-push-action@v1
with:
dockerfile: pusher/Dockerfile
path: ./
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: thecodingmachine/workadventure-pusher
tags: ${{ env.GITHUB_REF_SLUG }}
add_git_labels: true
build-uploader:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
# Create a slugified value of the branch
- uses: rlespinasse/github-slug-action@3.1.0
- name: "Build and push back image"
uses: docker/build-push-action@v1
with:
dockerfile: uploader/Dockerfile
path: ./
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: thecodingmachine/workadventure-uploader
tags: ${{ env.GITHUB_REF_SLUG }}
add_git_labels: true
build-maps:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
# Create a slugified value of the branch
- uses: rlespinasse/github-slug-action@3.1.0
- name: "Build and push front image"
uses: docker/build-push-action@v1
with:
dockerfile: maps/Dockerfile
path: maps/
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: thecodingmachine/workadventure-maps
tags: ${{ env.GITHUB_REF_SLUG }}
add_git_labels: true
deeploy:
needs:
- build-front
- build-back
- build-pusher
- build-maps
- build-uploader
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
# Create a slugified value of the branch
- uses: rlespinasse/github-slug-action@3.1.0
- name: Deploy
uses: thecodingmachine/deeployer-action@master
env:
KUBE_CONFIG_FILE: ${{ secrets.KUBE_CONFIG_FILE }}
ADMIN_API_TOKEN: ${{ secrets.ADMIN_API_TOKEN }}
JITSI_ISS: ${{ secrets.JITSI_ISS }}
JITSI_URL: ${{ secrets.JITSI_URL }}
SECRET_JITSI_KEY: ${{ secrets.SECRET_JITSI_KEY }}
TURN_STATIC_AUTH_SECRET: ${{ secrets.TURN_STATIC_AUTH_SECRET }}
with:
namespace: workadventure-${{ env.GITHUB_REF_SLUG }}
- name: Add a comment in PR
uses: unsplash/comment-on-pr@v1.2.0
if: ${{ env.GITHUB_REF_SLUG != 'master' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
msg: Environment deployed at https://play.${{ env.GITHUB_REF_SLUG }}.workadventure.test.thecodingmachine.com
check_for_duplicate_msg: true

View File

@ -1,26 +0,0 @@
name: Cleanup images and environments
on:
- delete
# Enables BuildKit
env:
DOCKER_BUILDKIT: 1
jobs:
delete_namespace:
runs-on: ubuntu-latest
steps:
# Create a slugified value of the branch
- uses: rlespinasse/github-slug-action@1.1.0
- name: Cleanup
uses: thecodingmachine/deeployer-cleanup-action@master
env:
KUBE_CONFIG_FILE: ${{ secrets.KUBE_CONFIG_FILE }}
with:
# FIXME: we are not using ${{ env.GITHUB_REF_SLUG }} that resolves to master BUT! we are not using a slugified namespace
# so complex namespace names will not be treated correctly
namespace: workadventure-${{ github.event.ref }}

View File

@ -3,8 +3,8 @@
name: "Continuous Integration"
on:
- "pull_request"
- "push"
push:
pull_request:
jobs:
@ -46,7 +46,7 @@ jobs:
- name: "Build"
run: yarn run build
env:
API_URL: "localhost:8080"
PUSHER_URL: "//localhost:8080"
working-directory: "front"
- name: "Lint"

3
.gitignore vendored
View File

@ -6,4 +6,5 @@ docker-compose.override.yaml
*.DS_Store
maps/yarn.lock
maps/dist/computer.js
maps/dist/computer.js.map
maps/dist/computer.js.map
contrib/docker/acme

36
CHANGELOG.md Normal file
View File

@ -0,0 +1,36 @@
## 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
- Added the emote feature to WorkAdventure. (@Kharhamel, @Tabascoeye)
- The emote menu can be opened by clicking on your character.
- Clicking on one of its element will close the menu and play an emote above your character.
- This emote can be seen by other players.
- Mobile support has been improved
- WorkAdventure automatically sets the zoom level based on the viewport size to ensure a sensible size of the map is visible, whatever the viewport used
- Mouse wheel support to zoom in / out
- Pinch support on mobile to zoom in / out
- Improved virtual joystick size (adapts to the zoom level)
- New scripting API features:
- Use `WA.loadSound(): Sound` to load / play / stop a sound
### Bug Fixes
- Pinch gesture does no longer move the character
## Version 1.3.0
### New Features
* Maps can now contain "group" layers (layers that contain other layers) - #899 #779 (@Lurkars @moufmouf)
### Updates
### Bug Fixes

View File

@ -20,7 +20,7 @@ Install Docker.
Run:
```
docker-compose up
docker-compose up -d
```
The environment will start.

View File

@ -11,6 +11,7 @@ const HTTP_PORT = parseInt(process.env.HTTP_PORT || '8080') || 8080;
const GRPC_PORT = parseInt(process.env.GRPC_PORT || '50051') || 50051;
export const SOCKET_IDLE_TIMER = parseInt(process.env.SOCKET_IDLE_TIMER as string) || 30; // maximum time (in second) without activity before a socket is closed
export const TURN_STATIC_AUTH_SECRET = process.env.TURN_STATIC_AUTH_SECRET || '';
export const MAX_PER_GROUP = parseInt(process.env.MAX_PER_GROUP || '4');
export {
MINIMUM_DISTANCE,

View File

@ -1,9 +1,3 @@
import { Group } from "./Group";
import { PointInterface } from "./Websocket/PointInterface";
import {Zone} from "_Model/Zone";
import {Movable} from "_Model/Movable";
import {PositionNotifier} from "_Model/PositionNotifier";
import {ServerDuplexStream} from "grpc";
import {
BatchMessage,
PusherToBackMessage,
@ -11,7 +5,6 @@ import {
ServerToClientMessage,
SubMessage, UserJoinedRoomMessage, UserLeftRoomMessage
} from "../Messages/generated/messages_pb";
import {CharacterLayer} from "_Model/Websocket/CharacterLayer";
import {AdminSocket} from "../RoomManager";

View File

@ -2,12 +2,12 @@ import {PointInterface} from "./Websocket/PointInterface";
import {Group} from "./Group";
import {User, UserSocket} from "./User";
import {PositionInterface} from "_Model/PositionInterface";
import {EntersCallback, LeavesCallback, MovesCallback} from "_Model/Zone";
import {EmoteCallback, EntersCallback, LeavesCallback, MovesCallback} from "_Model/Zone";
import {PositionNotifier} from "./PositionNotifier";
import {Movable} from "_Model/Movable";
import {extractDataFromPrivateRoomId, extractRoomSlugPublicRoomId, isRoomAnonymous} from "./RoomIdentifier";
import {arrayIntersect} from "../Services/ArrayHelper";
import {JoinRoomMessage} from "../Messages/generated/messages_pb";
import {EmoteEventMessage, JoinRoomMessage} from "../Messages/generated/messages_pb";
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
import {ZoneSocket} from "src/RoomManager";
import {Admin} from "../Model/Admin";
@ -38,12 +38,10 @@ export class GameRoom {
private readonly positionNotifier: PositionNotifier;
public readonly roomId: string;
public readonly anonymous: boolean;
public tags: string[];
public policyType: GameRoomPolicyTypes;
public readonly roomSlug: string;
public readonly worldSlug: string = '';
public readonly organizationSlug: string = '';
private versionNumber:number = 1;
private nextUserId: number = 1;
constructor(roomId: string,
@ -53,14 +51,12 @@ export class GameRoom {
groupRadius: number,
onEnters: EntersCallback,
onMoves: MovesCallback,
onLeaves: LeavesCallback)
{
onLeaves: LeavesCallback,
onEmote: EmoteCallback,
) {
this.roomId = roomId;
this.anonymous = isRoomAnonymous(roomId);
this.tags = [];
this.policyType = GameRoomPolicyTypes.ANONYMOUS_POLICY;
if (this.anonymous) {
if (isRoomAnonymous(roomId)) {
this.roomSlug = extractRoomSlugPublicRoomId(this.roomId);
} else {
const {organizationSlug, worldSlug, roomSlug} = extractDataFromPrivateRoomId(this.roomId);
@ -79,7 +75,7 @@ export class GameRoom {
this.minDistance = minDistance;
this.groupRadius = groupRadius;
// A zone is 10 sprites wide.
this.positionNotifier = new PositionNotifier(320, 320, onEnters, onMoves, onLeaves);
this.positionNotifier = new PositionNotifier(320, 320, onEnters, onMoves, onLeaves, onEmote);
}
public getGroups(): Group[] {
@ -110,7 +106,8 @@ export class GameRoom {
socket,
joinRoomMessage.getTagList(),
joinRoomMessage.getName(),
ProtobufUtils.toCharacterLayerObjects(joinRoomMessage.getCharacterlayerList())
ProtobufUtils.toCharacterLayerObjects(joinRoomMessage.getCharacterlayerList()),
joinRoomMessage.getCompanion()
);
this.nextUserId++;
this.users.set(user.id, user);
@ -304,10 +301,6 @@ export class GameRoom {
return this.itemsState;
}
public canAccess(userTags: string[]): boolean {
return arrayIntersect(userTags, this.tags);
}
public addZoneListener(call: ZoneSocket, x: number, y: number): Set<Movable> {
return this.positionNotifier.addZoneListener(call, x, y);
}
@ -328,4 +321,13 @@ export class GameRoom {
public adminLeave(admin: Admin): void {
this.admins.delete(admin);
}
public incrementVersion(): number {
this.versionNumber++
return this.versionNumber;
}
public emitEmoteEvent(user: User, emoteEventMessage: EmoteEventMessage) {
this.positionNotifier.emitEmoteEvent(user, emoteEventMessage);
}
}

View File

@ -4,9 +4,9 @@ import {PositionInterface} from "_Model/PositionInterface";
import {Movable} from "_Model/Movable";
import {PositionNotifier} from "_Model/PositionNotifier";
import {gaugeManager} from "../Services/GaugeManager";
import {MAX_PER_GROUP} from "../Enum/EnvironmentVariable";
export class Group implements Movable {
static readonly MAX_PER_GROUP = 4;
private static nextId: number = 1;
@ -88,7 +88,7 @@ export class Group implements Movable {
}
isFull(): boolean {
return this.users.size >= Group.MAX_PER_GROUP;
return this.users.size >= MAX_PER_GROUP;
}
isEmpty(): boolean {

View File

@ -8,10 +8,12 @@
* The PositionNotifier is important for performance. It allows us to send the position of players only to a restricted
* number of players around the current player.
*/
import {EntersCallback, LeavesCallback, MovesCallback, Zone} from "./Zone";
import {EmoteCallback, EntersCallback, LeavesCallback, MovesCallback, Zone} from "./Zone";
import {Movable} from "_Model/Movable";
import {PositionInterface} from "_Model/PositionInterface";
import {ZoneSocket} from "../RoomManager";
import {User} from "_Model/User";
import {EmoteEventMessage} from "../Messages/generated/messages_pb";
interface ZoneDescriptor {
i: number;
@ -24,7 +26,7 @@ export class PositionNotifier {
private zones: Zone[][] = [];
constructor(private zoneWidth: number, private zoneHeight: number, private onUserEnters: EntersCallback, private onUserMoves: MovesCallback, private onUserLeaves: LeavesCallback) {
constructor(private zoneWidth: number, private zoneHeight: number, private onUserEnters: EntersCallback, private onUserMoves: MovesCallback, private onUserLeaves: LeavesCallback, private onEmote: EmoteCallback) {
}
private getZoneDescriptorFromCoordinates(x: number, y: number): ZoneDescriptor {
@ -77,7 +79,7 @@ export class PositionNotifier {
let zone = this.zones[j][i];
if (zone === undefined) {
zone = new Zone(this.onUserEnters, this.onUserMoves, this.onUserLeaves, i, j);
zone = new Zone(this.onUserEnters, this.onUserMoves, this.onUserLeaves, this.onEmote, i, j);
this.zones[j][i] = zone;
}
return zone;
@ -93,4 +95,11 @@ export class PositionNotifier {
const zone = this.getZone(x, y);
zone.removeListener(call);
}
public emitEmoteEvent(user: User, emoteEventMessage: EmoteEventMessage) {
const zoneDesc = this.getZoneDescriptorFromCoordinates(user.getPosition().x, user.getPosition().y);
const zone = this.getZone(zoneDesc.i, zoneDesc.j);
zone.emitEmoteEvent(emoteEventMessage);
}
}

View File

@ -4,7 +4,7 @@ import {Zone} from "_Model/Zone";
import {Movable} from "_Model/Movable";
import {PositionNotifier} from "_Model/PositionNotifier";
import {ServerDuplexStream} from "grpc";
import {BatchMessage, PusherToBackMessage, ServerToClientMessage, SubMessage} from "../Messages/generated/messages_pb";
import {BatchMessage, CompanionMessage, PusherToBackMessage, ServerToClientMessage, SubMessage} from "../Messages/generated/messages_pb";
import {CharacterLayer} from "_Model/Websocket/CharacterLayer";
export type UserSocket = ServerDuplexStream<PusherToBackMessage, ServerToClientMessage>;
@ -23,7 +23,8 @@ export class User implements Movable {
public readonly socket: UserSocket,
public readonly tags: string[],
public readonly name: string,
public readonly characterLayers: CharacterLayer[]
public readonly characterLayers: CharacterLayer[],
public readonly companion?: CompanionMessage
) {
this.listenedZones = new Set<Zone>();

View File

@ -3,21 +3,19 @@ import {PositionInterface} from "_Model/PositionInterface";
import {Movable} from "./Movable";
import {Group} from "./Group";
import {ZoneSocket} from "../RoomManager";
import {EmoteEventMessage} from "../Messages/generated/messages_pb";
export type EntersCallback = (thing: Movable, fromZone: Zone|null, listener: ZoneSocket) => void;
export type MovesCallback = (thing: Movable, position: PositionInterface, listener: ZoneSocket) => void;
export type LeavesCallback = (thing: Movable, newZone: Zone|null, listener: ZoneSocket) => void;
export type EmoteCallback = (emoteEventMessage: EmoteEventMessage, listener: ZoneSocket) => void;
export class Zone {
private things: Set<Movable> = new Set<Movable>();
private listeners: Set<ZoneSocket> = new Set<ZoneSocket>();
/**
* @param x For debugging purpose only
* @param y For debugging purpose only
*/
constructor(private onEnters: EntersCallback, private onMoves: MovesCallback, private onLeaves: LeavesCallback, public readonly x: number, public readonly y: number) {
}
constructor(private onEnters: EntersCallback, private onMoves: MovesCallback, private onLeaves: LeavesCallback, private onEmote: EmoteCallback, public readonly x: number, public readonly y: number) { }
/**
* A user/thing leaves the zone
@ -41,9 +39,7 @@ export class Zone {
*/
private notifyLeft(thing: Movable, newZone: Zone|null) {
for (const listener of this.listeners) {
//if (listener !== thing && (newZone === null || !listener.listenedZones.has(newZone))) {
this.onLeaves(thing, newZone, listener);
//}
this.onLeaves(thing, newZone, listener);
}
}
@ -57,15 +53,6 @@ export class Zone {
*/
private notifyEnter(thing: Movable, oldZone: Zone|null, position: PositionInterface) {
for (const listener of this.listeners) {
/*if (listener === thing) {
continue;
}
if (oldZone === null || !listener.listenedZones.has(oldZone)) {
this.onEnters(thing, listener);
} else {
this.onMoves(thing, position, listener);
}*/
this.onEnters(thing, oldZone, listener);
}
}
@ -85,28 +72,6 @@ export class Zone {
}
}
/*public startListening(listener: User): void {
for (const thing of this.things) {
if (thing !== listener) {
this.onEnters(thing, listener);
}
}
this.listeners.add(listener);
listener.listenedZones.add(this);
}
public stopListening(listener: User): void {
for (const thing of this.things) {
if (thing !== listener) {
this.onLeaves(thing, listener);
}
}
this.listeners.delete(listener);
listener.listenedZones.delete(this);
}*/
public getThings(): Set<Movable> {
return this.things;
}
@ -119,4 +84,11 @@ export class Zone {
public removeListener(socket: ZoneSocket): void {
this.listeners.delete(socket);
}
public emitEmoteEvent(emoteEventMessage: EmoteEventMessage) {
for (const listener of this.listeners) {
this.onEmote(emoteEventMessage, listener);
}
}
}

View File

@ -5,12 +5,13 @@ import {
AdminPusherToBackMessage,
AdminRoomMessage,
BanMessage,
EmotePromptMessage,
EmptyMessage,
ItemEventMessage,
JoinRoomMessage,
PlayGlobalMessage,
PusherToBackMessage,
QueryJitsiJwtMessage,
QueryJitsiJwtMessage, RefreshRoomPromptMessage,
ServerToAdminClientMessage,
ServerToClientMessage,
SilentMessage,
@ -71,6 +72,8 @@ const roomManager: IRoomManagerServer = {
socketManager.emitPlayGlobalMessage(room, message.getPlayglobalmessage() as PlayGlobalMessage);
} else if (message.hasQueryjitsijwtmessage()){
socketManager.handleQueryJitsiJwtMessage(user, message.getQueryjitsijwtmessage() as QueryJitsiJwtMessage);
} else if (message.hasEmotepromptmessage()){
socketManager.handleEmoteEventMessage(room, user, message.getEmotepromptmessage() as EmotePromptMessage);
}else if (message.hasSendusermessage()) {
const sendUserMessage = message.getSendusermessage();
if(sendUserMessage !== undefined) {
@ -193,6 +196,10 @@ const roomManager: IRoomManagerServer = {
socketManager.dispatchWorlFullWarning(call.request.getRoomid());
callback(null, new EmptyMessage());
},
sendRefreshRoomPrompt(call: ServerUnaryCall<RefreshRoomPromptMessage>, callback: sendUnaryData<EmptyMessage>): void {
socketManager.dispatchRoomRefresh(call.request.getRoomid());
callback(null, new EmptyMessage());
},
};
export {roomManager};

View File

@ -1,49 +0,0 @@
import {ADMIN_API_TOKEN, ADMIN_API_URL} from "../Enum/EnvironmentVariable";
import Axios from "axios";
export interface AdminApiData {
organizationSlug: string
worldSlug: string
roomSlug: string
mapUrlStart: string
tags: string[]
policy_type: number
userUuid: string
messages?: unknown[],
textures: CharacterTexture[]
}
export interface CharacterTexture {
id: number,
level: number,
url: string,
rights: string
}
class AdminApi {
async fetchMapDetails(organizationSlug: string, worldSlug: string, roomSlug: string|undefined): Promise<AdminApiData> {
if (!ADMIN_API_URL) {
return Promise.reject('No admin backoffice set!');
}
const params: { organizationSlug: string, worldSlug: string, roomSlug?: string } = {
organizationSlug,
worldSlug
};
if (roomSlug) {
params.roomSlug = roomSlug;
}
const res = await Axios.get(ADMIN_API_URL + '/api/map',
{
headers: {"Authorization": `${ADMIN_API_TOKEN}`},
params
}
)
return res.data;
}
}
export const adminApi = new AdminApi();

View File

@ -26,7 +26,8 @@ import {
GroupLeftZoneMessage,
WorldFullWarningMessage,
UserLeftZoneMessage,
BanUserMessage,
EmoteEventMessage,
BanUserMessage, RefreshRoomMessage, EmotePromptMessage,
} from "../Messages/generated/messages_pb";
import {User, UserSocket} from "../Model/User";
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
@ -41,7 +42,6 @@ import {
} from "../Enum/EnvironmentVariable";
import {Movable} from "../Model/Movable";
import {PositionInterface} from "../Model/PositionInterface";
import {adminApi, CharacterTexture} from "./AdminApi";
import Jwt from "jsonwebtoken";
import {JITSI_URL} from "../Enum/EnvironmentVariable";
import {clientEventsEmitter} from "./ClientEventsEmitter";
@ -68,6 +68,7 @@ export class SocketManager {
private rooms: Map<string, GameRoom> = new Map<string, GameRoom>();
constructor() {
clientEventsEmitter.registerToClientJoin((clientUUid: string, roomId: string) => {
gaugeManager.incNbClientPerRoomGauge(roomId);
});
@ -129,15 +130,7 @@ export class SocketManager {
if (viewport === undefined) {
throw new Error('Viewport not found in message');
}
// sending to all clients in room except sender
/*client.position = {
x: position.x,
y: position.y,
direction,
moving: position.moving,
};
client.viewport = viewport;*/
// update position in the world
room.updatePosition(user, ProtobufUtils.toPointInterface(position));
@ -192,21 +185,6 @@ export class SocketManager {
}
}
// TODO: handle this message in pusher
/*async handleReportMessage(client: ExSocketInterface, reportPlayerMessage: ReportPlayerMessage) {
try {
const reportedSocket = this.sockets.get(reportPlayerMessage.getReporteduserid());
if (!reportedSocket) {
throw 'reported socket user not found';
}
//TODO report user on admin application
await adminApi.reportPlayer(reportedSocket.userUuid, reportPlayerMessage.getReportcomment(), client.userUuid)
} catch (e) {
console.error('An error occurred on "handleReportMessage"');
console.error(e);
}
}*/
emitVideo(room: GameRoom, user: User, data: WebRtcSignalToServerMessage): void {
//send only at user
const remoteUser = room.getUsers().get(data.getReceiverid());
@ -287,13 +265,9 @@ export class SocketManager {
GROUP_RADIUS,
(thing: Movable, fromZone: Zone|null, listener: ZoneSocket) => this.onZoneEnter(thing, fromZone, listener),
(thing: Movable, position:PositionInterface, listener: ZoneSocket) => this.onClientMove(thing, position, listener),
(thing: Movable, newZone: Zone|null, listener: ZoneSocket) => this.onClientLeave(thing, newZone, listener)
(thing: Movable, newZone: Zone|null, listener: ZoneSocket) => this.onClientLeave(thing, newZone, listener),
(emoteEventMessage:EmoteEventMessage, listener: ZoneSocket) => this.onEmote(emoteEventMessage, listener),
);
if (!world.anonymous) {
const data = await adminApi.fetchMapDetails(world.organizationSlug, world.worldSlug, world.roomSlug)
world.tags = data.tags
world.policyType = Number(data.policy_type)
}
gaugeManager.incNbRoomGauge();
this.rooms.set(roomId, world);
}
@ -325,6 +299,7 @@ export class SocketManager {
userJoinedZoneMessage.setCharacterlayersList(ProtobufUtils.toCharacterLayerMessages(thing.characterLayers));
userJoinedZoneMessage.setPosition(ProtobufUtils.toPositionMessage(thing.getPosition()));
userJoinedZoneMessage.setFromzone(this.toProtoZone(fromZone));
userJoinedZoneMessage.setCompanion(thing.companion);
const subMessage = new SubToPusherMessage();
subMessage.setUserjoinedzonemessage(userJoinedZoneMessage);
@ -367,6 +342,14 @@ export class SocketManager {
}
}
private onEmote(emoteEventMessage: EmoteEventMessage, client: ZoneSocket) {
const subMessage = new SubToPusherMessage();
subMessage.setEmoteeventmessage(emoteEventMessage);
emitZoneMessage(subMessage, client);
}
private emitCreateUpdateGroupEvent(client: ZoneSocket, fromZone: Zone|null, group: Group): void {
const position = group.getPosition();
const pointMessage = new PointMessage();
@ -538,19 +521,6 @@ export class SocketManager {
return this.rooms;
}
/**
*
* @param token
*/
/*searchClientByUuid(uuid: string): ExSocketInterface | null {
for(const socket of this.sockets.values()){
if(socket.userUuid === uuid){
return socket;
}
}
return null;
}*/
public handleQueryJitsiJwtMessage(user: User, queryJitsiJwtMessage: QueryJitsiJwtMessage) {
const room = queryJitsiJwtMessage.getJitsiroom();
@ -634,6 +604,7 @@ export class SocketManager {
userJoinedMessage.setName(thing.name);
userJoinedMessage.setCharacterlayersList(ProtobufUtils.toCharacterLayerMessages(thing.characterLayers));
userJoinedMessage.setPosition(ProtobufUtils.toPositionMessage(thing.getPosition()));
userJoinedMessage.setCompanion(thing.companion);
const subMessage = new SubToPusherMessage();
subMessage.setUserjoinedzonemessage(userJoinedMessage);
@ -772,6 +743,32 @@ export class SocketManager {
recipient.socket.write(clientMessage);
});
}
dispatchRoomRefresh(roomId: string,): void {
const room = this.rooms.get(roomId);
if (!room) {
return;
}
const versionNumber = room.incrementVersion();
room.getUsers().forEach((recipient) => {
const worldFullMessage = new RefreshRoomMessage();
worldFullMessage.setRoomid(roomId)
worldFullMessage.setVersionnumber(versionNumber)
const clientMessage = new ServerToClientMessage();
clientMessage.setRefreshroommessage(worldFullMessage);
recipient.socket.write(clientMessage);
});
}
handleEmoteEventMessage(room: GameRoom, user: User, emotePromptMessage: EmotePromptMessage) {
const emoteEventMessage = new EmoteEventMessage();
emoteEventMessage.setEmote(emotePromptMessage.getEmote());
emoteEventMessage.setActoruserid(user.id);
room.emitEmoteEvent(user, emoteEventMessage);
}
}
export const socketManager = new SocketManager();

View File

@ -5,6 +5,7 @@ import {Group} from "../src/Model/Group";
import {User, UserSocket} from "_Model/User";
import {JoinRoomMessage, PositionMessage} from "../src/Messages/generated/messages_pb";
import Direction = PositionMessage.Direction;
import {EmoteCallback} from "_Model/Zone";
function createMockUser(userId: number): User {
return {
@ -33,6 +34,8 @@ function createJoinRoomMessage(uuid: string, x: number, y: number): JoinRoomMess
return joinRoomMessage;
}
const emote: EmoteCallback = (emoteEventMessage, listener): void => {}
describe("GameRoom", () => {
it("should connect user1 and user2", () => {
let connectCalledNumber: number = 0;
@ -43,7 +46,8 @@ describe("GameRoom", () => {
}
const world = new GameRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {});
const world = new GameRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {}, emote);
@ -72,7 +76,7 @@ describe("GameRoom", () => {
}
const world = new GameRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {});
const world = new GameRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {}, emote);
const user1 = world.join(createMockUserSocket(), createJoinRoomMessage('1', 100, 100));
@ -101,7 +105,7 @@ describe("GameRoom", () => {
disconnectCallNumber++;
}
const world = new GameRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {});
const world = new GameRoom('_/global/test.json', connect, disconnect, 160, 160, () => {}, () => {}, () => {}, emote);
const user1 = world.join(createMockUserSocket(), createJoinRoomMessage('1', 100, 100));

View File

@ -23,7 +23,7 @@ describe("PositionNotifier", () => {
moveTriggered = true;
}, (thing: Movable) => {
leaveTriggered = true;
});
}, () => {});
const user1 = new User(1, 'test', '10.0.0.2', {
x: 500,
@ -98,7 +98,7 @@ describe("PositionNotifier", () => {
moveTriggered = true;
}, (thing: Movable) => {
leaveTriggered = true;
});
}, () => {});
const user1 = new User(1, 'test', '10.0.0.2', {
x: 500,

View File

@ -1251,9 +1251,9 @@ has-values@^1.0.0:
kind-of "^4.0.0"
hosted-git-info@^2.1.4:
version "2.8.8"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
version "2.8.9"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
http-errors@1.7.2:
version "1.7.2"
@ -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"
@ -3032,9 +3032,9 @@ xtend@^4.0.0:
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
y18n@^3.2.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
version "3.2.2"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696"
integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==
yallist@^3.0.0, yallist@^3.0.3:
version "3.1.1"

View File

@ -230,9 +230,9 @@
}
},
"hosted-git-info": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg=="
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="
},
"indent-string": {
"version": "2.1.0",

View File

@ -169,8 +169,8 @@ graceful-fs@^4.1.2:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
hosted-git-info@^2.1.4:
version "2.8.8"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
version "2.8.9"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
indent-string@^2.1.0:
version "2.1.0"

View File

@ -0,0 +1,41 @@
## The single (sub)domain to use
BASE_DOMAIN=wa.example.com
DEBUG_MODE=false
## JITSI settings
JITSI_URL=meet.jit.si
# If your Jitsi environment has authentication set up, you MUST set JITSI_PRIVATE_MODE to "true" and you MUST pass a SECRET_JITSI_KEY to generate the JWT secret
JITSI_PRIVATE_MODE=false
JITSI_ISS=
SECRET_JITSI_KEY=
## ADMIN backend settings
ADMIN_API_TOKEN=2342
ADMIN_API_URL=
## TURN server settings
# URL of the TURN server (needed to "punch a hole" through some networks for P2P connections)
STUN_SERVER=
TURN_SERVER=
TURN_USER=
TURN_PASSWORD=
## Reverse proxy settings (note: these must also be manually activated in the docker-compose file for now)
TRAEFIK_BASICAUTH=testuser:$2y$05$L2t/Wx937mHhKH61mjPL7OvepvjcyUnzVUkpiMo.nKeWSdRd5oyUC
TRAEFIK_BASICAUTHFILE=/.htpasswd
# Maximum allowed number of people per "ring" group
MAX_PER_GROUP=5
# Maximum length allowed for nicknames
MAX_USERNAME_LENGTH=12
# The URL used by default, in the form: "/_/global/map/url.json" or with active admin backend as "/@/org/world/room"
START_ROOM_URL=/_/global/maps.workadventu.re/Floor0/floor0.json
# The email address used by Let's encrypt to send renewal warnings (compulsory)
ACME_EMAIL=
# Set to true to allow using this instance as a target for the apiUrl property
FEDERATE_PUSHER=false

View File

@ -18,3 +18,6 @@ START_ROOM_URL=/_/global/maps.workadventu.re/Floor0/floor0.json
# The email address used by Let's encrypt to send renewal warnings (compulsory)
ACME_EMAIL=
# Set to true to allow using this instance as a target for the apiUrl property
FEDERATE_PUSHER=false

0
contrib/docker/.htpasswd Normal file
View File

View File

@ -0,0 +1,73 @@
version: '3'
services:
reverse-proxy:
image: traefik:v2.4
depends_on:
- front
- pusher
command:
- --providers.docker
- --entryPoints.web.address=:80
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:z
privileged: true
front:
build:
context: ../..
dockerfile: front/Dockerfile
args:
START_ROOM_URL: "$START_ROOM_URL"
JITSI_PRIVATE_MODE: "$JITSI_PRIVATE_MODE"
JITSI_URL: "$JITSI_URL"
STUN_SERVER: "$STUN_SERVER"
TURN_SERVER: "$TURN_SERVER"
TURN_USER: "$TURN_USER"
TURN_PASSWORD: "$TURN_PASSWORD"
environment:
DEBUG_MODE: "$DEBUG_MODE"
labels:
- "traefik.http.routers.front.rule=PathPrefix(`/`)"
- "traefik.http.routers.front.entryPoints=web"
- "traefik.http.services.front.loadbalancer.server.port=8000"
pusher:
build:
context: ../..
dockerfile: pusher/Dockerfile
depends_on:
- back
environment:
SECRET_KEY: yourSecretKey
SECRET_JITSI_KEY: "$SECRET_JITSI_KEY"
ADMIN_API_TOKEN: "$ADMIN_API_TOKEN"
API_URL: back:50051
JITSI_URL: $JITSI_URL
JITSI_ISS: $JITSI_ISS
ports:
- "9378:8080"
labels:
- "traefik.http.middlewares.strip-pusher-prefix.stripprefix.prefixes=/pusher"
- "traefik.http.routers.pusher.rule=PathPrefix(`/pusher`)"
- "traefik.http.routers.pusher.middlewares=strip-pusher-prefix@docker"
- "traefik.http.routers.pusher.entryPoints=web"
- "traefik.http.services.pusher.loadbalancer.server.port=8080"
back:
build:
context: ../..
dockerfile: back/Dockerfile
environment:
SECRET_KEY: yourSecretKey
SECRET_JITSI_KEY: "$SECRET_JITSI_KEY"
ADMIN_API_TOKEN: "$ADMIN_API_TOKEN"
JITSI_URL: $JITSI_URL
JITSI_ISS: $JITSI_ISS
labels:
- "traefik.http.middlewares.strip-api-prefix.stripprefix.prefixes=/api"
- "traefik.http.routers.back.rule=PathPrefix(`/api`)"
- "traefik.http.routers.back.middlewares=strip-api-prefix@docker"
- "traefik.http.routers.back.entryPoints=web"
- "traefik.http.services.back.loadbalancer.server.port=8080"

View File

@ -0,0 +1,145 @@
version: "3"
services:
reverse-proxy:
image: traefik:v2.3.7
restart: unless-stopped
command:
- --providers.docker
- --entryPoints.web.address=:80
- --entrypoints.web.http.redirections.entryPoint.to=websecure
- --entrypoints.web.http.redirections.entryPoint.scheme=https
- --entrypoints.web.http.redirections.entrypoint.permanent=true
- --entryPoints.websecure.address=:443
- --providers.file.directory=/configs/
- --certificatesresolvers.myhttpchallenge.acme.tlschallenge=true
- --certificatesresolvers.myhttpchallenge.acme.email=$ACME_EMAIL
- --certificatesresolvers.myhttpchallenge.acme.storage=/acme/acme.json
# uncomment for debugging traefik
# - --log.level=DEBUG
ports:
- "80:80"
- "443:443"
depends_on:
- back
- front
- uploader
- pusher
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./acme:/acme
- ./traefik_tls.yaml:/configs/traefik_tls.yml
- ./.htpasswd:/.htpasswd
front:
restart: unless-stopped
build:
context: ../..
dockerfile: front/Dockerfile
args:
BASE_DOMAIN: ${BASE_DOMAIN:-workadventure.localhost}
# These should fall back to window.location.host
PUSHER_URL: /pusher
UPLOADER_URL: /uploader
ADMIN_URL: /admin
MAPS_URL: /maps
START_ROOM_URL: "$START_ROOM_URL"
JITSI_PRIVATE_MODE: "$JITSI_PRIVATE_MODE"
JITSI_URL: "$JITSI_URL"
START_ROOM_URL: "$START_ROOM_URL"
STUN_SERVER: "$STUN_SERVER"
TURN_PASSWORD: "$TURN_PASSWORD"
TURN_SERVER: "$TURN_SERVER"
TURN_USER: "$TURN_USER"
MAX_PER_GROUP: $MAX_PER_GROUP
MAX_USERNAME_LENGTH: $MAX_USERNAME_LENGTH
labels:
- "traefik.http.routers.front.rule=Host(`${BASE_DOMAIN}`) && PathPrefix(`/`)"
- "traefik.http.routers.front.entryPoints=web,websecure"
- "traefik.http.services.front.loadbalancer.server.port=8000"
- "traefik.http.routers.front.tls=true"
- "traefik.http.routers.front.service=front"
- "traefik.http.routers.front.tls.certresolver=myhttpchallenge"
# uncomment to enable user/pass basic auth
# - "traefik.http.routers.front.middlewares=auth"
# - "traefik.http.middlewares.auth.basicauth.users=${TRAEFIK_BASICAUTH}"
# - "traefik.http.middlewares.auth.basicauth.usersFile=${TRAEFIK_BASICAUTHFILE}"
# - "traefik.http.middlewares.auth.basicauth.headerField=X-WebAuth-User"
pusher:
restart: unless-stopped
build:
context: ../..
dockerfile: pusher/Dockerfile
environment:
SECRET_KEY: yourSecretKey
SECRET_JITSI_KEY: "$SECRET_JITSI_KEY"
ADMIN_API_TOKEN: "$ADMIN_API_TOKEN"
ADMIN_API_URL: "$ADMIN_API_URL"
API_URL: back:50051
JITSI_URL: $JITSI_URL
JITSI_ISS: $JITSI_ISS
FEDERATE_PUSHER: $FEDERATE_PUSHER
labels:
- "traefik.http.middlewares.strip-pusher-prefix.stripprefix.prefixes=/pusher"
- "traefik.http.routers.pusher.rule=Host(`${BASE_DOMAIN}`) && PathPrefix(`/pusher`)"
- "traefik.http.routers.pusher.middlewares=strip-pusher-prefix@docker"
- "traefik.http.routers.pusher.entryPoints=web,websecure"
- "traefik.http.services.pusher.loadbalancer.server.port=8080"
- "traefik.http.routers.pusher.tls=true"
- "traefik.http.routers.pusher.service=pusher"
back:
restart: unless-stopped
build:
context: ../..
dockerfile: back/Dockerfile
environment:
SECRET_KEY: yourSecretKey
SECRET_JITSI_KEY: "$SECRET_JITSI_KEY"
ADMIN_API_TOKEN: "$ADMIN_API_TOKEN"
ADMIN_API_URL: "$ADMIN_API_URL"
JITSI_URL: $JITSI_URL
JITSI_ISS: $JITSI_ISS
MAX_PER_GROUP: $MAX_PER_GROUP
labels:
- "traefik.http.middlewares.strip-api-prefix.stripprefix.prefixes=/api"
- "traefik.http.routers.back.rule=Host(`${BASE_DOMAIN}`) && PathPrefix(`/api`)"
- "traefik.http.routers.back.middlewares=strip-api-prefix@docker"
- "traefik.http.routers.back.entryPoints=web,websecure"
- "traefik.http.services.back.loadbalancer.server.port=8080"
- "traefik.http.routers.back.tls=true"
- "traefik.http.routers.back.service=back"
uploader:
restart: unless-stopped
build:
context: ../..
dockerfile: uploader/Dockerfile
labels:
- "traefik.http.middlewares.strip-uploader-prefix.stripprefix.prefixes=/uploader"
- "traefik.http.routers.uploader.rule=Host(`${BASE_DOMAIN}`) && PathPrefix(`/uploader`)"
- "traefik.http.routers.uploader.middlewares=strip-uploader-prefix@docker"
- "traefik.http.routers.uploader.entryPoints=web,websecure"
- "traefik.http.services.uploader.loadbalancer.server.port=8080"
- "traefik.http.routers.uploader.tls=true"
- "traefik.http.routers.uploader.service=uploader"
maps:
restart: unless-stopped
build:
context: ../..
dockerfile: maps/Dockerfile
volumes:
- ../../maps:/var/www/html/
labels:
- "traefik.http.middlewares.strip-maps-prefix.stripprefix.prefixes=/maps"
- "traefik.http.routers.maps.rule=Host(`${BASE_DOMAIN}`) && PathPrefix(`/maps`)"
- "traefik.http.routers.maps.middlewares=strip-maps-prefix@docker"
- "traefik.http.routers.maps.entryPoints=web,websecure"
- "traefik.http.services.maps.loadbalancer.server.port=80"
- "traefik.http.routers.maps.tls=true"
- "traefik.http.routers.maps.service=maps"

View File

@ -37,7 +37,7 @@ services:
DEBUG_MODE: "$DEBUG_MODE"
JITSI_URL: $JITSI_URL
JITSI_PRIVATE_MODE: "$JITSI_PRIVATE_MODE"
API_URL: pusher.${DOMAIN}
PUSHER_URL: //pusher.${DOMAIN}
TURN_SERVER: "${TURN_SERVER}"
TURN_USER: "${TURN_USER}"
TURN_PASSWORD: "${TURN_PASSWORD}"
@ -65,6 +65,7 @@ services:
API_URL: back:50051
JITSI_URL: $JITSI_URL
JITSI_ISS: $JITSI_ISS
FEDERATE_PUSHER: $FEDERATE_PUSHER
labels:
- "traefik.http.routers.pusher.rule=Host(`pusher.${DOMAIN}`)"
- "traefik.http.routers.pusher.entryPoints=web,traefik"

View File

@ -0,0 +1,13 @@
tls:
options:
default:
sniStrict: true
minVersion: VersionTLS12
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305

View File

@ -0,0 +1,115 @@
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
@font-face {
font-family: "Press Start 2P";
src: url(PressStart2P-Regular.ttf);
}
canvas {
float: left;
border: 1px solid black;
}
h1 {
font-family: "Press Start 2P";
font-size: 20px;
}
.setting {
font-family: "Press Start 2P";
font-size: 12px;
}
.generator input {
height: 64px;
display: inline-block;
float: left;
margin: 0 1em 0 1em;
}
.generator textarea {
width: 256px;
height: 512px;
display: inline-block;
float: left;
}
</style>
<script type="text/javascript" >
function drawText () {
var fontName = document.getElementById("fontName").value;
var fontColor = document.getElementById("fontColor").value;
var marginTop = Number(document.getElementById("marginTop").value);
var marginLeft = Number(document.getElementById("marginLeft").value);
var fontSize = document.getElementById("fontSize").value;
var fontInfo = fontSize + "px " + fontName;
var lines = document.getElementById("textToDraw").value.split('\n');
var canvas = document.getElementById("textCanvas");
var canvasContext = canvas.getContext("2d");
var tileHeight = 32
var maxRows = (canvas.height / tileHeight) - 1;
var row = 0;
var column = 0;
canvasContext.font = fontInfo;
canvasContext.fillStyle = fontColor;
canvasContext.textAlign = "left";
canvasContext.textBaseline = "hanging";
canvasContext.clearRect(0, 0, canvas.width, canvas.height);
for(var n=0; n<lines.length; n++) {
var x = (column * 128) + marginLeft;
var y = (row * tileHeight) + marginTop;
canvasContext.fillText(lines[n], x, y, 128-marginLeft);
row++;
if(row > maxRows)
{
column++;
row = 0;
}
}
}
</script>
</head>
<body>
<h1>Text to Tiles</h1>
<p>Jede Zeile wird linksbündig in ein Feld von 128px x 32px geschrieben.</p>
<p>Das Bild kann per Rechtsklick mit "Bild speichern" direkt als Tileset verwendet oder mit "Bild kopieren" in ein Grafikprogramm übernommen werden.</p>
<form>
<div class="setting">
<label>Font</label> <input id="fontName" value="&quot;Press Start 2P&quot;" style="width:15em"; />
</div>
<div class="setting">
<label>Size</label> <input id="fontSize" value="8" style="width:3em"; /> px
</div>
<div class="setting">
<label>Margin top</label> <input id="marginTop" value="18" style="width:3em"; /> px
</div>
<div class="setting">
<label>Margin left</label> <input id="marginLeft" value="20" style="width:3em"; /> px
</div>
<div class="setting">
<label>Color</label> <input id="fontColor" value="#cccccc" style="width:7em"; />
</div>
</form>
<form class="generator">
<textarea id="textToDraw"></textarea>
<input type="button" value="Draw =>" onclick="drawText();" />
</form>
<div style="overflow:scroll;width:512px;height:512px">
<canvas width="1056" height="1056" id="textCanvas"></canvas>
</div>
</body>
</html>

69
contrib/tools/update.sh Executable file
View File

@ -0,0 +1,69 @@
#!/bin/sh -e
# vim: ts=4 sw=4 et
# --- V A R I A B L E S --- #
SCRIPT_NAME=$(basename "$0")
# --- S U B R O U T I N E S --- #
print_help_message_and_exit() {
cat << EOM
usage: $SCRIPT_NAME [-h]
$SCRIPT_NAME -f
$SCRIPT_NAME [-f] [-b] <cntnr>
$SCRIPT_NAME [-f] -r
Cleanly rebuilds the Docker image of a container and restarts all containers.
options:
-b do not restart containers; only rebuild Docker image
-f fetches new commits and resets (--hard !) to origin/xce
-h show this help message
-r do not rebuild Docker imags; only restart containers
positional arguments:
cntnr name of the container whose image should be rebuilt
EOM
exit
}
# --- M A I N S C R I P T --- #
# Parse commnand line
fetch=no
rebuild=yes
reboot=yes
while getopts "fbhr" option; do
case $option in
b) reboot=no ;;
f) fetch=yes ;;
r) rebuild=no ;;
*) print_help_message_and_exit ;;
esac
done
shift $((OPTIND - 1))
CONTAINER=$1
if [ -z "$CONTAINER" ] && [ "$rebuild" = 'yes' ]; then
print_help_message_and_exit
fi
# Fetch
if [ "$fetch" = 'yes' ]; then
git fetch
git reset --hard origin/xce
fi
# Rebuild
if [ -n "$CONTAINER" ] && [ "$rebuild" = 'yes' ]; then
docker system prune -f
docker-compose build --no-cache "$CONTAINER"
fi
if [ "$reboot" = 'yes' ]; then
docker-compose down
docker-compose up -d
fi

View File

@ -1,8 +1,8 @@
{
local env = std.extVar("env"),
local namespace = env.GITHUB_REF_SLUG,
local namespace = env.DEPLOY_REF,
local tag = namespace,
local url = if namespace == "master" then "workadventu.re" else namespace+".workadventure.test.thecodingmachine.com",
local url = namespace+".test.workadventu.re",
// develop branch does not use admin because of issue with SSL certificate of admin as of now.
local adminUrl = if namespace == "master" || namespace == "develop" || std.startsWith(namespace, "admin") then "https://"+url else null,
"$schema": "https://raw.githubusercontent.com/thecodingmachine/deeployer/master/deeployer.schema.json",
@ -25,10 +25,7 @@
"TURN_STATIC_AUTH_SECRET": env.TURN_STATIC_AUTH_SECRET,
} + (if adminUrl != null then {
"ADMIN_API_URL": adminUrl,
} else {}) + if namespace != "master" then {
// Absolutely ugly WorkAround to circumvent broken certificates on the K8S test cluster. Don't do this in production kids!
"NODE_TLS_REJECT_UNAUTHORIZED": "0"
}
} else {})
},
"back2": {
"image": "thecodingmachine/workadventure-back:"+tag,
@ -47,10 +44,7 @@
"TURN_STATIC_AUTH_SECRET": env.TURN_STATIC_AUTH_SECRET,
} + (if adminUrl != null then {
"ADMIN_API_URL": adminUrl,
} else {}) + if namespace != "master" then {
// Absolutely ugly WorkAround to circumvent broken certificates on the K8S test cluster. Don't do this in production kids!
"NODE_TLS_REJECT_UNAUTHORIZED": "0"
}
} else {})
},
"pusher": {
"replicas": 2,
@ -69,10 +63,7 @@
"SECRET_JITSI_KEY": env.SECRET_JITSI_KEY,
} + (if adminUrl != null then {
"ADMIN_API_URL": adminUrl,
} else {}) + if namespace != "master" then {
// Absolutely ugly WorkAround to circumvent broken certificates on the K8S test cluster. Don't do this in production kids!
"NODE_TLS_REJECT_UNAUTHORIZED": "0"
}
} else {})
},
"front": {
"image": "thecodingmachine/workadventure-front:"+tag,
@ -82,14 +73,12 @@
},
"ports": [80],
"env": {
"API_URL": "pusher."+url,
"UPLOADER_URL": "uploader."+url,
"ADMIN_URL": url,
"PUSHER_URL": "//pusher."+url,
"UPLOADER_URL": "//uploader."+url,
"ADMIN_URL": "//"+url,
"JITSI_URL": env.JITSI_URL,
"SECRET_JITSI_KEY": env.SECRET_JITSI_KEY,
"TURN_SERVER": "turn:coturn.workadventu.re:443,turns:coturn.workadventu.re:443",
"TURN_USER": "workadventure",
"TURN_PASSWORD": "WorkAdventure123",
"JITSI_PRIVATE_MODE": if env.SECRET_JITSI_KEY != '' then "true" else "false",
"START_ROOM_URL": "/_/global/maps."+url+"/Floor0/floor0.json"
//"GA_TRACKING_ID": "UA-10196481-11"

83
docker-compose.bk.yaml Normal file
View File

@ -0,0 +1,83 @@
version: "3"
services:
# the frontend is only built here - it is served directly via nginx
front:
image: thecodingmachine/nodejs:14
environment:
DEBUG_MODE: "$DEBUG_MODE"
JITSI_URL: "$JITSI_URL"
JITSI_PRIVATE_MODE: "$JITSI_PRIVATE_MODE"
NODE_ENV: development
PUSHER_URL: "//pusher.$DOMAIN"
UPLOADER_URL: "//uploader.$DOMAIN"
STARTUP_COMMAND_1: ./templater.sh
STARTUP_COMMAND_2: yarn install
STUN_SERVER: "stun:stun.l.google.com:19302"
TURN_SERVER: "turn:coturn.workadventu.re:443,turns:coturn.workadventu.re:443"
DISABLE_NOTIFICATIONS: "$DISABLE_NOTIFICATIONS"
SKIP_RENDER_OPTIMIZATIONS: "$SKIP_RENDER_OPTIMIZATIONS"
# Use TURN_USER/TURN_PASSWORD if your Coturn server is secured via hard coded credentials.
# Advice: you should instead use Coturn REST API along the TURN_STATIC_AUTH_SECRET in the Back container
TURN_USER: ""
TURN_PASSWORD: ""
START_ROOM_URL: "$START_ROOM_URL"
MAX_PER_GROUP: "$MAX_PER_GROUP"
MAX_USERNAME_LENGTH: "$MAX_USERNAME_LENGTH"
command: yarn run build
volumes:
- ./front:/usr/src/app
pusher:
image: thecodingmachine/nodejs:12
environment:
DEBUG: "socket:*"
STARTUP_COMMAND_1: yarn install
SECRET_JITSI_KEY: "$SECRET_JITSI_KEY"
SECRET_KEY: yourSecretKey
ADMIN_API_TOKEN: "$ADMIN_API_TOKEN"
API_URL: back:50051
JITSI_URL: "$JITSI_URL"
JITSI_ISS: "$JITSI_ISS"
FEDERATE_PUSHER: $FEDERATE_PUSHER
command: yarn run prod
ports:
- "127.0.0.1:8002:8080"
volumes:
- ./pusher:/usr/src/app
back:
image: thecodingmachine/nodejs:12
environment:
DEBUG: "*"
STARTUP_COMMAND_1: yarn install
SECRET_KEY: yourSecretKey
SECRET_JITSI_KEY: "$SECRET_JITSI_KEY"
ALLOW_ARTILLERY: "true"
ADMIN_API_TOKEN: "$ADMIN_API_TOKEN"
JITSI_URL: "$JITSI_URL"
JITSI_ISS: "$JITSI_ISS"
TURN_STATIC_AUTH_SECRET: SomeStaticAuthSecret
MAX_PER_GROUP: "MAX_PER_GROUP"
command: yarn run prod
volumes:
- ./back:/usr/src/app
uploader:
image: thecodingmachine/nodejs:12
environment:
DEBUG: "*"
STARTUP_COMMAND_1: yarn install
command: yarn run prod
ports:
- "127.0.0.1:8005:8080"
volumes:
- ./uploader:/usr/src/app
messages:
#image: thecodingmachine/nodejs:14
image: thecodingmachine/workadventure-back-base:latest
environment:
#STARTUP_COMMAND_0: sudo apt-get install -y inotify-tools
STARTUP_COMMAND_1: yarn install
STARTUP_COMMAND_2: yarn run proto:watch
volumes:
- ./messages:/usr/src/app
- ./back:/usr/src/back
- ./front:/usr/src/front
- ./pusher:/usr/src/pusher

View File

@ -0,0 +1,194 @@
version: "3"
services:
reverse-proxy:
image: traefik:v2.0
command:
- --api.insecure=true
- --providers.docker
- --entryPoints.web.address=:80
- --entryPoints.websecure.address=:443
ports:
- "80:80"
- "443:443"
# The Web UI (enabled by --api.insecure=true)
- "8080:8080"
depends_on:
- back
- front
volumes:
- /var/run/docker.sock:/var/run/docker.sock
front:
image: thecodingmachine/nodejs:14
environment:
DEBUG_MODE: "$DEBUG_MODE"
JITSI_URL: $JITSI_URL
JITSI_PRIVATE_MODE: "$JITSI_PRIVATE_MODE"
HOST: "0.0.0.0"
NODE_ENV: development
PUSHER_URL: /pusher
UPLOADER_URL: /uploader
ADMIN_URL: /admin
MAPS_URL: /maps
STARTUP_COMMAND_1: ./templater.sh
STARTUP_COMMAND_2: yarn install
TURN_SERVER: "turn:localhost:3478,turns:localhost:5349"
DISABLE_NOTIFICATIONS: "$DISABLE_NOTIFICATIONS"
SKIP_RENDER_OPTIMIZATIONS: "$SKIP_RENDER_OPTIMIZATIONS"
# Use TURN_USER/TURN_PASSWORD if your Coturn server is secured via hard coded credentials.
# Advice: you should instead use Coturn REST API along the TURN_STATIC_AUTH_SECRET in the Back container
TURN_USER: ""
TURN_PASSWORD: ""
START_ROOM_URL: "$START_ROOM_URL"
command: yarn run start
volumes:
- ./front:/usr/src/app
labels:
- "traefik.http.routers.front.rule=PathPrefix(`/`)"
- "traefik.http.routers.front.entryPoints=web,traefik"
- "traefik.http.services.front.loadbalancer.server.port=8080"
- "traefik.http.routers.front-ssl.rule=PathPrefix(`/`)"
- "traefik.http.routers.front-ssl.entryPoints=websecure"
- "traefik.http.routers.front-ssl.tls=true"
- "traefik.http.routers.front-ssl.service=front"
pusher:
image: thecodingmachine/nodejs:12
command: yarn dev
#command: yarn run prod
#command: yarn run profile
environment:
DEBUG: "*"
STARTUP_COMMAND_1: yarn install
SECRET_JITSI_KEY: "$SECRET_JITSI_KEY"
SECRET_KEY: yourSecretKey
ADMIN_API_TOKEN: "$ADMIN_API_TOKEN"
API_URL: back:50051
JITSI_URL: $JITSI_URL
JITSI_ISS: $JITSI_ISS
volumes:
- ./pusher:/usr/src/app
labels:
- "traefik.http.middlewares.strip-pusher-prefix.stripprefix.prefixes=/pusher"
- "traefik.http.routers.pusher.rule=PathPrefix(`/pusher`)"
- "traefik.http.routers.pusher.middlewares=strip-pusher-prefix@docker"
- "traefik.http.routers.pusher.entryPoints=web"
- "traefik.http.services.pusher.loadbalancer.server.port=8080"
- "traefik.http.routers.pusher-ssl.rule=PathPrefix(`/pusher`)"
- "traefik.http.routers.pusher-ssl.middlewares=strip-pusher-prefix@docker"
- "traefik.http.routers.pusher-ssl.entryPoints=websecure"
- "traefik.http.routers.pusher-ssl.tls=true"
- "traefik.http.routers.pusher-ssl.service=pusher"
maps:
image: thecodingmachine/nodejs:12-apache
environment:
DEBUG_MODE: "$DEBUG_MODE"
HOST: "0.0.0.0"
NODE_ENV: development
#APACHE_DOCUMENT_ROOT: dist/
#APACHE_EXTENSIONS: headers
#APACHE_EXTENSION_HEADERS: 1
STARTUP_COMMAND_0: sudo a2enmod headers
STARTUP_COMMAND_1: yarn install
STARTUP_COMMAND_2: yarn run dev &
volumes:
- ./maps:/var/www/html
labels:
- "traefik.http.middlewares.strip-maps-prefix.stripprefix.prefixes=/maps"
- "traefik.http.routers.maps.rule=PathPrefix(`/maps`)"
- "traefik.http.routers.maps.middlewares=strip-maps-prefix@docker"
- "traefik.http.routers.maps.entryPoints=web,traefik"
- "traefik.http.services.maps.loadbalancer.server.port=80"
- "traefik.http.routers.maps-ssl.rule=PathPrefix(`/maps`)"
- "traefik.http.routers.maps-ssl.middlewares=strip-maps-prefix@docker"
- "traefik.http.routers.maps-ssl.entryPoints=websecure"
- "traefik.http.routers.maps-ssl.tls=true"
- "traefik.http.routers.maps-ssl.service=maps"
back:
image: thecodingmachine/nodejs:12
command: yarn dev
#command: yarn run profile
environment:
DEBUG: "*"
STARTUP_COMMAND_1: yarn install
SECRET_KEY: yourSecretKey
SECRET_JITSI_KEY: "$SECRET_JITSI_KEY"
ALLOW_ARTILLERY: "true"
ADMIN_API_TOKEN: "$ADMIN_API_TOKEN"
JITSI_URL: $JITSI_URL
JITSI_ISS: $JITSI_ISS
MAX_PER_GROUP: "$MAX_PER_GROUP"
volumes:
- ./back:/usr/src/app
labels:
- "traefik.http.middlewares.strip-api-prefix.stripprefix.prefixes=/api"
- "traefik.http.routers.back.rule=PathPrefix(`/api`)"
- "traefik.http.routers.back.middlewares=strip-api-prefix@docker"
- "traefik.http.routers.back.entryPoints=web"
- "traefik.http.services.back.loadbalancer.server.port=8080"
- "traefik.http.routers.back-ssl.rule=PathPrefix(`/api`)"
- "traefik.http.routers.back-ssl.middlewares=strip-api-prefix@docker"
- "traefik.http.routers.back-ssl.entryPoints=websecure"
- "traefik.http.routers.back-ssl.tls=true"
- "traefik.http.routers.back-ssl.service=back"
uploader:
image: thecodingmachine/nodejs:12
command: yarn dev
#command: yarn run profile
environment:
DEBUG: "*"
STARTUP_COMMAND_1: yarn install
volumes:
- ./uploader:/usr/src/app
labels:
- "traefik.http.middlewares.strip-uploader-prefix.stripprefix.prefixes=/uploader"
- "traefik.http.routers.uploader.rule=PathPrefix(`/uploader`)"
- "traefik.http.routers.uploader.middlewares=strip-uploader-prefix@docker"
- "traefik.http.routers.uploader.entryPoints=web"
- "traefik.http.services.uploader.loadbalancer.server.port=8080"
- "traefik.http.routers.uploader-ssl.rule=PathPrefix(`/uploader`)"
- "traefik.http.routers.uploader-ssl.middlewares=strip-uploader-prefix@docker"
- "traefik.http.routers.uploader-ssl.entryPoints=websecure"
- "traefik.http.routers.uploader-ssl.tls=true"
- "traefik.http.routers.uploader-ssl.service=uploader"
messages:
#image: thecodingmachine/nodejs:14
image: thecodingmachine/workadventure-back-base:latest
environment:
#STARTUP_COMMAND_0: sudo apt-get install -y inotify-tools
STARTUP_COMMAND_1: yarn install
STARTUP_COMMAND_2: yarn run proto:watch
volumes:
- ./messages:/usr/src/app
- ./back:/usr/src/back
- ./front:/usr/src/front
- ./pusher:/usr/src/pusher
# coturn:
# image: coturn/coturn:4.5.2
# command:
# - turnserver
# #- -c=/etc/coturn/turnserver.conf
# - --log-file=stdout
# - --external-ip=$$(detect-external-ip)
# - --listening-port=3478
# - --min-port=10000
# - --max-port=10010
# - --tls-listening-port=5349
# - --listening-ip=0.0.0.0
# - --realm=localhost
# - --server-name=localhost
# - --lt-cred-mech
# # Enable Coturn "REST API" to validate temporary passwords.
# #- --use-auth-secret
# #- --static-auth-secret=SomeStaticAuthSecret
# #- --userdb=/var/lib/turn/turndb
# - --user=workadventure:WorkAdventure123
# # use real-valid certificate/privatekey files
# #- --cert=/root/letsencrypt/fullchain.pem
# #- --pkey=/root/letsencrypt/privkey.pem
# network_mode: host

View File

@ -26,24 +26,28 @@ services:
JITSI_PRIVATE_MODE: "$JITSI_PRIVATE_MODE"
HOST: "0.0.0.0"
NODE_ENV: development
API_URL: pusher.workadventure.localhost
UPLOADER_URL: uploader.workadventure.localhost
ADMIN_URL: workadventure.localhost
PUSHER_URL: //pusher.workadventure.localhost
UPLOADER_URL: //uploader.workadventure.localhost
ADMIN_URL: //workadventure.localhost
STARTUP_COMMAND_1: ./templater.sh
STARTUP_COMMAND_2: yarn install
STUN_SERVER: "stun:stun.l.google.com:19302"
TURN_SERVER: "turn:coturn.workadventure.localhost:3478,turns:coturn.workadventure.localhost:5349"
DISABLE_NOTIFICATIONS: "$DISABLE_NOTIFICATIONS"
SKIP_RENDER_OPTIMIZATIONS: "$SKIP_RENDER_OPTIMIZATIONS"
# Use TURN_USER/TURN_PASSWORD if your Coturn server is secured via hard coded credentials.
# Advice: you should instead use Coturn REST API along the TURN_STATIC_AUTH_SECRET in the Back container
TURN_USER: ""
TURN_PASSWORD: ""
START_ROOM_URL: "$START_ROOM_URL"
MAX_PER_GROUP: "$MAX_PER_GROUP"
MAX_USERNAME_LENGTH: "$MAX_USERNAME_LENGTH"
command: yarn run start
volumes:
- ./front:/usr/src/app
labels:
- "traefik.http.routers.front.rule=Host(`play.workadventure.localhost`)"
- "traefik.http.routers.front.entryPoints=web,traefik"
- "traefik.http.routers.front.entryPoints=web"
- "traefik.http.services.front.loadbalancer.server.port=8080"
- "traefik.http.routers.front-ssl.rule=Host(`play.workadventure.localhost`)"
- "traefik.http.routers.front-ssl.entryPoints=websecure"
@ -62,6 +66,7 @@ services:
API_URL: back:50051
JITSI_URL: $JITSI_URL
JITSI_ISS: $JITSI_ISS
FEDERATE_PUSHER: $FEDERATE_PUSHER
volumes:
- ./pusher:/usr/src/app
labels:
@ -110,6 +115,7 @@ services:
JITSI_URL: $JITSI_URL
JITSI_ISS: $JITSI_ISS
TURN_STATIC_AUTH_SECRET: SomeStaticAuthSecret
MAX_PER_GROUP: "MAX_PER_GROUP"
volumes:
- ./back:/usr/src/app
labels:

237
docs/maps/api-reference.md Normal file
View File

@ -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.
<div>
<figure class="figure">
<img src="https://workadventu.re/img/docs/trigger_event.png" class="figure-img img-fluid rounded" alt="" />
<figcaption class="figure-caption">The `zone` property, applied on a layer</figcaption>
</figure>
</div>
* **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.
<div class="row">
<div class="col">
<img src="https://workadventu.re/img/docs/screen_popup_tiled.png" class="figure-img img-fluid rounded" alt="" />
</div>
<div class="col">
<img src="https://workadventu.re/img/docs/screen_popup_in_game.png" class="figure-img img-fluid rounded" alt="" />
</div>
</div>
```
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();
```

117
docs/maps/scripting.md Normal file
View File

@ -0,0 +1,117 @@
{.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}
# 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"_.
<div>
<figure class="figure">
<img src="https://workadventu.re/img/docs/admin/map_properties.png" class="figure-img img-fluid rounded" alt="" />
<figcaption class="figure-caption">The Map properties menu</figcaption>
</figure>
</div>
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.
<div>
<figure class="figure">
<img src="https://workadventu.re/img/docs/script_property.png" class="figure-img img-fluid rounded" alt="" />
<figcaption class="figure-caption">The script property</figcaption>
</figure>
</div>
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".
<div>
<figure class="figure">
<img src="https://workadventu.re/img/docs/open_website_allow_api.png" class="figure-img img-fluid rounded" alt="" />
<figcaption class="figure-caption">The `openWebsiteAllowApi` property</figcaption>
</figure>
</div>
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
<!doctype html>
<html lang="en">
<head>
<script src="https://play.workadventu.re/iframe_api.js"></script>
</head>
<body>
</body>
</html>
```
You can now start by testing this with a simple message sent to the chat.
**iframe.html**
```html
...
<script>
WA.sendChatMessage('Hello world', 'Mr Robot');
</script>
...
```
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
The list of available functions and features is [available in the API Reference page, with examples](api-reference).

View File

@ -25,6 +25,15 @@
],
"rules": {
"no-unused-vars": "off",
"@typescript-eslint/no-explicit-any": "error"
"@typescript-eslint/no-explicit-any": "error",
// TODO: remove those ignored rules and write a stronger code!
"@typescript-eslint/no-floating-promises": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/restrict-plus-operands": "off",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/restrict-template-expressions": "off"
}
}

View File

@ -4,6 +4,7 @@ WORKDIR /usr/src
COPY messages .
RUN yarn install && yarn proto
# webpack build
FROM node:14-buster-slim as builder2
WORKDIR /usr/src
@ -14,6 +15,28 @@ COPY front .
COPY --from=builder /usr/src/generated src/Messages/generated
ENV NODE_ENV=production
# Removing the iframe.html file from the final image as this adds a XSS attack.
# iframe.html is only in dev mode to circumvent a limitation
RUN rm dist/iframe.html
ARG PUSHER_URL=/pusher
ARG ADMIN_URL=/admin
ARG MAPS_URL=/maps
ARG UPLOADER_URL=/uploader
ARG START_ROOM_URL
ARG JITSI_PRIVATE_MODE
ARG JITSI_URL
ARG STUN_SERVER
ARG TURN_SERVER
ARG TURN_USER
ARG TURN_PASSWORD
ARG MAX_USERNAME_LENGTH
ARG MAX_PER_GROUP
COPY front .
COPY --from=builder /usr/src/generated src/Messages/generated
ENV NODE_ENV=production
ARG ADMIN_URL=admin.$BASE_DOMAIN
ARG API_URL=pusher.$BASE_DOMAIN
ARG BASE_DOMAIN=workadventure.localhost
@ -29,7 +52,8 @@ ARG UPLOADER_URL=uploader.$BASE_DOMAIN
RUN ./templater.sh
RUN API_URL=$API_URL UPLOADER_URL=$UPLOADER_URL ADMIN_URL=$ADMIN_URL START_ROOM_URL=$START_ROOM_URL \
JITSI_URL=$JITSI_URL JITSI_PRIVATE_MODE=$JITSI_PRIVATE_MODE \
STUN_SERVER=$STUN_SERVER TURN_SERVER=$TURN_SERVER TURN_USER=$TURN_USER TURN_PASSWORD=$TURN_PASSWORD \
STUN_SERVER=$STUN_SERVER TURN_SERVER=$TURN_SERVER TURN_USER=$TURN_USER \
TURN_PASSWORD=$TURN_PASSWORD MAX_USERNAME_LENGTH=$MAX_USERNAME_LENGTH MAX_PER_GROUP=$MAX_PER_GROUP \
yarn run build
# final production image

View File

@ -1,3 +1,4 @@
index.html
index.tmpl.html.tmp
style.*.css
/js/
style.*.css

17
front/dist/iframe.html vendored Normal file
View File

@ -0,0 +1,17 @@
<!doctype html>
<html lang="en">
<head>
<script src="/iframe_api.js" ></script>
<script>
// Note: this is a huge XSS flow as we allow anyone to load a Javascript file in our domain.
// This file must ABSOLUTELY be removed from the Docker images/deployments and is only here
// for development purpose (because dynamically generated iframes are not working with
// webpack hot reload due to an issue with rights)
const urlParams = new URLSearchParams(window.location.search);
const scriptUrl = urlParams.get('script');
const script = document.createElement('script');
script.src = scriptUrl;
document.head.append(script);
</script>
</head>
</html>

View File

@ -29,12 +29,17 @@
<base href="/">
<link href="https://fonts.googleapis.com/css?family=Press+Start+2P" rel="stylesheet">
<link href="https://unpkg.com/nes.css@2.3.0/css/nes.min.css" rel="stylesheet" />
<title>Binary Kitchen World</title>
</head>
<body id="body" style="margin: 0; background-color: #000">
<div class="main-container" id="main-container">
<!-- Create the editor container -->
<div id="game" class="game">
<div id="svelte-overlay">
</div>
<div id="game-overlay" class="game-overlay">
<div id="main-section" class="main-section">
</div>
@ -51,23 +56,29 @@
<div id="activeCam" class="activeCam">
<div id="div-myCamVideo" class="video-container">
<video id="myCamVideo" autoplay muted></video>
<div id="mySoundMeter" class="sound-progress">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
</div>
<div class="btn-cam-action">
<div id="btn-micro" class="btn-micro">
<img id="microphone" src="resources/logos/microphone.svg">
<img id="microphone-close" src="resources/logos/microphone-close.svg">
<div id="btn-monitor" class="btn-monitor">
<img id="monitor" src="resources/logos/monitor.svg">
<img id="monitor-close" src="resources/logos/monitor-close.svg">
</div>
<div id="btn-video" class="btn-video">
<img id="cinema" src="resources/logos/cinema.svg">
<img id="cinema-close" src="resources/logos/cinema-close.svg">
</div>
<div id="btn-monitor" class="btn-monitor">
<img id="monitor" src="resources/logos/monitor.svg">
<img id="monitor-close" src="resources/logos/monitor-close.svg">
<div id="btn-micro" class="btn-micro">
<img id="microphone" src="resources/logos/microphone.svg">
<img id="microphone-close" src="resources/logos/microphone-close.svg">
</div>
</div>
</div>
</div>
<div id="cowebsite" class="cowebsite hidden">
@ -76,11 +87,11 @@
</aside>
<main id="cowebsite-main">
</main>
<button class="top-right-btn" id="cowebsite-fullscreen">
<img id="cowebsite-fullscreen-open" src="resources/logos/monitor.svg"/>
<img id="cowebsite-fullscreen-close" style="display: none;" src="resources/logos/monitor-close.svg"/>
<button class="top-right-btn" id="cowebsite-fullscreen" alt="fullscreen mode">
<img id="cowebsite-fullscreen-open" src="resources/logos/fullscreen.svg"/>
<img id="cowebsite-fullscreen-close" style="display: none;" src="resources/logos/fullscreen-exit.svg"/>
</button>
<button class="top-right-btn" id="cowebsite-close">
<button class="top-right-btn" id="cowebsite-close" alt="close the iframe">
<img src="resources/logos/close.svg"/>
</button>
</div>
@ -91,9 +102,15 @@
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-volume-up" fill="white" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M6.717 3.55A.5.5 0 0 1 7 4v8a.5.5 0 0 1-.812.39L3.825 10.5H1.5A.5.5 0 0 1 1 10V6a.5.5 0 0 1 .5-.5h2.325l2.363-1.89a.5.5 0 0 1 .529-.06zM6 5.04L4.312 6.39A.5.5 0 0 1 4 6.5H2v3h2a.5.5 0 0 1 .312.11L6 10.96V5.04z" />
<g id="audioplayer_volume_icon_playing">
<path d="M11.536 14.01A8.473 8.473 0 0 0 14.026 8a8.473 8.473 0 0 0-2.49-6.01l-.708.707A7.476 7.476 0 0 1 13.025 8c0 2.071-.84 3.946-2.197 5.303l.708.707z" />
<path d="M10.121 12.596A6.48 6.48 0 0 0 12.025 8a6.48 6.48 0 0 0-1.904-4.596l-.707.707A5.483 5.483 0 0 1 11.025 8a5.483 5.483 0 0 1-1.61 3.89l.706.706z" />
<path d="M8.707 11.182A4.486 4.486 0 0 0 10.025 8a4.486 4.486 0 0 0-1.318-3.182L8 5.525A3.489 3.489 0 0 1 9.025 8 3.49 3.49 0 0 1 8 10.475l.707.707z" />
<g id="audioplayer_volume_icon_playing_high">
<path d="M11.536 14.01A8.473 8.473 0 0 0 14.026 8a8.473 8.473 0 0 0-2.49-6.01l-.708.707A7.476 7.476 0 0 1 13.025 8c0 2.071-.84 3.946-2.197 5.303l.708.707z" />
</g>
<g id="audioplayer_volume_icon_playing_mid">
<path d="M10.121 12.596A6.48 6.48 0 0 0 12.025 8a6.48 6.48 0 0 0-1.904-4.596l-.707.707A5.483 5.483 0 0 1 11.025 8a5.483 5.483 0 0 1-1.61 3.89l.706.706z" />
</g>
<g id="audioplayer_volume_icon_playing_low">
<path d="M8.707 11.182A4.486 4.486 0 0 0 10.025 8a4.486 4.486 0 0 0-1.318-3.182L8 5.525A3.489 3.489 0 0 1 9.025 8 3.49 3.49 0 0 1 8 10.475l.707.707z" />
</g>
</g>
</svg>
</button>
@ -102,13 +119,22 @@
</div>
</div>
<div class="audioplayer">
<label id="label-audioplayer_decrease_while_talking" for="audiooplayer_decrease_while_talking" title="decrease background volume by 50% when entering conversations">
<label id="label-audioplayer_decrease_while_talking" for="audioplayer_decrease_while_talking" title="decrease background volume by 50% when entering conversations">
reduce in conversations
<input type="checkbox" id="audioplayer_decrease_while_talking" checked />
</label>
<div id="audioplayer" style="visibility: hidden"></div>
</div>
</div>
<div id="videoplayerctrl" class="hidden">
<div class="videoplayer">
<div id="videoplayer"></div>
<label id="label-videoplayer_decrease_while_talking" for="videoplayer_decrease_while_talking" title="decrease background volume by 50% when entering conversations">
autoreduce
<input type="checkbox" id="videoplayer_decrease_while_talking" checked />
</label>
</div>
</div>
<div class="audio-playing">
<img src="/resources/logos/megaphone.svg" />
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

@ -0,0 +1,160 @@
<style>
*{
font-family: PixelFont-7,monospace!important;
}
#customizeScene {
background: #0000;
/*border: 1px solid #ebeeee;*/
border-radius: 6px;
margin: 10px auto 0;
color: #ebeeee;
width: 42vw;
height: 48vh;
/*max-width: 300px;
max-height: 48vh;*/
overflow: hidden;
}
#customizeScene h1 {
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
border-bottom: 1px solid #a6abaf;
border-radius: 6px 6px 0 0;
box-sizing: border-box;
color: #727678;
display: block;
height: 43px;
padding-top: 10px;
margin: 0;
text-align: center;
text-shadow: 0 -1px 0 rgba(0,0,0,0.2), 0 1px 0 #fff;
}
#customizeScene input {
font-size: 70%;
background: linear-gradient(top, #d6d7d7, #dee0e0);
border: 1px solid #a1a3a3;
border-radius: 4px;
box-shadow: 0 1px #fff;
box-sizing: border-box;
color: #696969;
height: 30px;
transition: box-shadow 0.3s;
width: 100%;
text-align: center;
}
#customizeScene section {
margin: 10px;
}
#customizeScene section.action {
text-align: center;
position: sticky;
bottom: 0;
top: 100%;
}
#customizeScene section.action.action-move {
top: 55%;
}
#customizeScene button {
margin: 2px 10px;
background-color: black;;
color: #ebeeee;
border-radius: 7px;
padding-bottom: 4px;
}
#customizeScene button#customizeSceneFormCancel {
background-color: #aca6a600;
color: #292929;
}
#customizeScene section h6,
#customizeScene section h5{
margin: 1px;
}
#customizeScene section.text-center{
text-align: center;
}
#customizeScene section a{
font-size: 14px;
text-decoration: underline;
color: #ebeeee;
}
#customizeScene section a:hover{
font-weight: 700;
}
#customizeScene section p{
text-align: left;
font-size: 8px;
margin: 10px 10px;
}
#customizeScene section p.err{
color: red;
text-align: center;
}
#customizeScene section p.info{
display: none;
text-align: center;
}
#customizeScene section input#customizeSceneLink{
background-color: #a1a3a3;
}
#customizeScene section button.customizeSceneButton{
position: absolute;
margin: 0;
top: -8vh;
font-size: 10px;
padding: 2px 4px;
}
#customizeScene section button.customizeSceneButton#customizeSceneButtonLeft{
left: 0vw;
}
#customizeScene section button.customizeSceneButton#customizeSceneButtonRight{
right: 0vw;
}
#customizeScene section button.customizeSceneButton#customizeSceneButtonUp{
left: calc(2vw + 40px);
transform: rotate(90deg);
margin-top: -20px;
}
#customizeScene section button.customizeSceneButton#customizeSceneButtonDown{
right: calc(2vw + 40px);
transform: rotate(90deg);
margin-top: 20px;
}
#customizeScene section.action img{
width: 8px;
height: 8px;
}
#customizeScene section.action a#customizeSceneFormBack img{
margin-top: -2px;
}
#customizeScene section.action button#customizeSceneFormSubmit img{
transform: rotate(180deg);
}
@media only screen and (max-width: 600px) {
#customizeScene {
max-width: 160px;
overflow-y: scroll;
}
}
@media only screen and (max-height: 400px) {
#customizeScene section.action {
top: 92%;
}
#customizeScene section.action.action-move {
top: 80%;
}
}
</style>
<form id="customizeScene" hidden>
<section class="text-center">
<h5>Custom your WOKA</h3>
</section>
<section class="action action-move">
<button class="customizeSceneButton" id="customizeSceneButtonLeft"> < </button>
<button class="customizeSceneButton" id="customizeSceneButtonRight"> > </button>
<!--<button class="customizeSceneButton" id="customizeSceneButtonUp"> < </button>
<button class="customizeSceneButton" id="customizeSceneButtonDown"> > </button>-->
</section>
<section class="action">
<a type="submit" id="customizeSceneFormBack">Back <img src="resources/objects/arrow_up.png"/></a>
<button type="submit" id="customizeSceneFormSubmit">Next <img src="resources/objects/arrow_up.png"/></button>
</section>
</form>

View File

@ -0,0 +1,129 @@
<style>
*{
font-family: PixelFont-7,monospace!important;
}
#enableCameraScene {
background: #000000;
/*border: 1px solid #ebeeee;*/
border-radius: 6px;
margin: 20px auto 0;
color: #ebeeee;
max-height: 48vh;
width: 42vw;
max-width: 300px;
overflow: hidden;
}
#enableCameraScene h1 {
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
border-bottom: 1px solid #a6abaf;
border-radius: 6px 6px 0 0;
box-sizing: border-box;
color: #727678;
display: block;
height: 43px;
padding-top: 10px;
margin: 0;
text-align: center;
text-shadow: 0 -1px 0 rgba(0,0,0,0.2), 0 1px 0 #fff;
}
#enableCameraScene input {
font-size: 70%;
background: linear-gradient(top, #d6d7d7, #dee0e0);
border: 1px solid #a1a3a3;
border-radius: 4px;
box-shadow: 0 1px #fff;
box-sizing: border-box;
color: #696969;
height: 30px;
transition: box-shadow 0.3s;
width: 100%;
text-align: center;
}
#enableCameraScene section.title {
position: absolute;
top: 1vh;
width: 100%;
}
#enableCameraScene section.action{
text-align: center;
margin: 0;
position: absolute;
top: 40vh;
width: 100%;
}
#enableCameraScene button {
margin: 10px;
background-color: black;;
color: #ebeeee;
border-radius: 7px;
padding-bottom: 4px;
}
#enableCameraScene button#enableCameraSceneFormCancel {
background-color: #c7c7c700;
color: #292929;
}
#enableCameraScene section h6,
#enableCameraScene section h5{
margin: 1px;
}
#enableCameraScene section.text-center{
text-align: center;
}
#enableCameraScene section a{
font-size: 8px;
text-decoration: underline;
color: #ebeeee;
}
#enableCameraScene section a:hover{
font-weight: 700;
}
#enableCameraScene section p{
text-align: left;
font-size: 8px;
margin: 10px 10px;
}
#enableCameraScene section p.err{
color: red;
text-align: center;
}
#enableCameraScene section p.info{
display: none;
text-align: center;
}
#enableCameraScene section input#enableCameraSceneLink{
background-color: #a1a3a3;
}
#enableCameraScene section img{
width: 160px;
margin: 20px 0;
}
/*@media only screen and (max-width: 800px),
only screen and (max-height: 600px) {
#enableCameraScene{
overflow-y: scroll;
}
}*/
</style>
<form id="enableCameraScene" hidden>
<!-- FIX me -->
<section class="title text-center">
<h5>Turn on your camera and microphone</h5>
</section>
<!--<section class="text-center">
<video id="myCamVideoSetup" autoplay muted></video>
</section>
<section class="text-center">
<h5>Select your camera</h3>
<select id="camera">
</select>
</section>
<section class="text-center">
<h5>Select your michrophone</h3>
<select id="michrophone">
</select>
</section>-->
<section class="action">
<button type="submit" id="enableCameraSceneFormSubmit">Let's go!</button>
</section>
</form>

View File

@ -0,0 +1,134 @@
<style>
*{
font-family: PixelFont-7,monospace!important;
}
#selectCompanionScene {
background: #0000;
/*border: 1px solid #ebeeee;*/
border-radius: 6px;
margin: 10px auto 0;
color: #ebeeee;
max-height: 40vh;
max-width: 300px;
width: 40vw;
overflow: hidden;
}
#selectCompanionScene h1 {
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
border-bottom: 1px solid #a6abaf;
border-radius: 6px 6px 0 0;
box-sizing: border-box;
color: #727678;
display: block;
height: 43px;
padding-top: 10px;
margin: 0;
text-align: center;
text-shadow: 0 -1px 0 rgba(0,0,0,0.2), 0 1px 0 #fff;
}
#selectCompanionScene input {
font-size: 70%;
background: linear-gradient(top, #d6d7d7, #dee0e0);
border: 1px solid #a1a3a3;
border-radius: 4px;
box-shadow: 0 1px #fff;
box-sizing: border-box;
color: #696969;
height: 30px;
transition: box-shadow 0.3s;
width: 100%;
text-align: center;
}
#selectCompanionScene section {
margin: 10px;
}
#selectCompanionScene section.action {
text-align: center;
margin: 0;
margin-top: 20vh;
}
#selectCompanionScene button {
margin: 10px 4px;
background-color: black;;
color: #ebeeee;
border-radius: 7px;
padding-bottom: 4px;
width: 100px;
}
#selectCompanionScene button#selectCompanionSceneFormCancel {
background-color: #aca6a600;
color: #292929;
}
#selectCompanionScene section h6,
#selectCompanionScene section h5{
margin: 1px;
}
#selectCompanionScene section.text-center{
text-align: center;
}
#selectCompanionScene section a{
font-size: 14px;
text-decoration: underline;
color: #ebeeee;
}
#selectCompanionScene section a:hover{
font-weight: 700;
}
#selectCompanionScene section p{
text-align: left;
font-size: 8px;
margin: 10px 10px;
}
#selectCompanionScene section p.err{
color: red;
text-align: center;
}
#selectCompanionScene section p.info{
display: none;
text-align: center;
}
#selectCompanionScene section input#selectCompanionSceneLink{
background-color: #a1a3a3;
}
#selectCompanionScene section img{
width: 160px;
margin: 20px 0;
}
#selectCompanionScene section button.selectCharacterButton{
position: absolute;
top: 20vh;
margin: 0;
width: 25px;
}
#selectCompanionScene section button.selectCharacterButton#selectCharacterButtonLeft{
left: 1vw;
}
#selectCompanionScene section button.selectCharacterButton#selectCharacterButtonRight{
right: 1vw;
}
#selectCompanionScene section button#selectCompanionSceneFormCustomYourOwnSubmit{
font-size: 14px;
width: auto;
margin-top: -2px;
background-color: #ffd700;
color: black;
}
@media only screen and (max-width: 800px),
only screen and (max-height: 600px) {
#selectCompanionScene{
overflow-y: scroll;
}
}
</style>
<form id="selectCompanionScene" hidden>
<section class="text-center">
<h5>Select your WOKA</h5>
<button class="selectCharacterButton" id="selectCharacterButtonLeft"> < </button>
<button class="selectCharacterButton" id="selectCharacterButtonRight"> > </button>
</section>
<section class="action">
<a herf="#" id="selectCompanionSceneFormBack">No companion</a>
<button type="submit" id="selectCompanionSceneFormSubmit">Continue</button>
</section>
</form>

View File

@ -1,6 +1,9 @@
<style>
#gameMenu {
pointer-events: auto;
*{
font-family: PixelFont-7,monospace!important;
}
#gameMenu main{
margin-top: 15px;
}
#gameMenu button {
background-color: black;
@ -11,13 +14,17 @@
#gameMenu section {
margin: 10px;
}
section#socialLinks{
position: absolute;
margin-bottom: 0;
}
section#socialLinks img{
width: 32px;
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
@media only screen and (max-height: 700px) {
#gameMenu main {
display: flex;
flex-direction: row;
align-items: flex-end;
flex-wrap: wrap;
margin-top: 0;
}
#gameMenu section{
margin: 2px;
}
}
</style>
@ -33,18 +40,17 @@
<section>
<button id="changeSkinButton">Edit skin</button>
</section>
<section>
<button id="changeCompanionButton">Edit companion</button>
</section>
<section>
<button id="editGameSettingsButton">Settings</button>
</section>
<section hidden>
<button id="sparkButton">Create map</button>
<section>
<button id="toggleFullscreen">Toggle fullscreen</button>
</section>
<section id="adminConsoleSection" hidden>
<button id="adminConsoleButton">Admin console</button>
</section>
<section id="socialLinks" hidden>
<a class="not-button" href="https://www.facebook.com/workadventurebytcm" target="_blank"><img class="not-button" src="/resources/objects/facebook-icon.png"/></a>
<a class="not-button" href="https://twitter.com/Workadventure_" target="_blank"><img class="not-button" src="/resources/objects/twitter-icon.png"/></a>
</section>
</main>
</div>

View File

@ -1,4 +1,7 @@
<style>
*{
font-family: PixelFont-7,monospace!important;
}
#menuIcon {
pointer-events: auto;
}
@ -6,17 +9,21 @@
background-color: black;
color: white;
border-radius: 7px;
height: 28px;
width: 34px;
padding: 2px 8px;
}
#menuIcon button img{
width: 14px;
padding-top: 3px;
padding-top: 0;
cursor: pointer;
}
#menuIcon section {
margin: 10px;
}
@media only screen and (max-height: 700px) {
#menuIcon section {
margin: 2px;
}
}
</style>
<main id="menuIcon" hidden>
<section>

View File

@ -1,12 +1,14 @@
<style>
*{
font-family: PixelFont-7,monospace!important;
}
#gameQuality {
background: #eceeee;
border: 1px solid #42464b;
border-radius: 6px;
height: 257px;
margin: 20px auto 0;
width: 298px;
pointer-events: auto;
width: 50vw;
max-width: 300px;
}
#gameQuality .cautiousText {
font-size: 50%;
@ -34,7 +36,7 @@
color: #696969;
height: 30px;
transition: box-shadow 0.3s;
width: 240px;
width: 100%;
}
#gameQuality section {
margin: 10px;
@ -43,12 +45,11 @@
text-align: center;
}
#gameQuality button {
margin-top: 10px;
margin: 10px;
background-color: black;
color: white;
border-radius: 7px;
padding-bottom: 4px;
width: 60px;
}
#gameQuality button#gameQualityFormCancel {
background-color: #c7c7c700;
@ -58,7 +59,7 @@
<form id="gameQuality" hidden>
<section>
<h3>Game quality</h3>
<h5>Game quality</h3>
<p class="cautiousText">(Editing these settings will restart the game)</p>
<select id="select-game-quality">
<option value="120">High video quality (120 fps)</option>
@ -68,7 +69,7 @@
</select>
</section>
<section>
<h3>Video quality</h3>
<h5>Video quality</h3>
<select id="select-video-quality">
<option value="30">High video quality (30 fps)</option>
<option value="20">Medium video quality (20 fps, recommended)</option>

View File

@ -1,4 +1,7 @@
<style>
*{
font-family: PixelFont-7,monospace!important;
}
#gameReport {
background: #eceeee;
border: 1px solid #42464b;

View File

@ -1,12 +1,14 @@
<style>
*{
font-family: PixelFont-7,monospace!important;
}
#gameShare {
background: #eceeee;
border: 1px solid #42464b;
border-radius: 6px;
margin: 20px auto 0;
width: 298px;
height: 150px;
pointer-events: auto;
width: 50vw;
max-width: 400px;
}
#gameShare h1 {
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
@ -41,7 +43,7 @@
margin: 0;
}
#gameShare button {
margin-top: 10px;
margin: 10px;
background-color: black;
color: white;
border-radius: 7px;
@ -67,7 +69,7 @@
}
#gameShare section p{
font-size: 8px;
margin: 0px 70px;
margin: 0;
}
#gameShare section p.err{
color: red;

View File

@ -1,12 +1,17 @@
<style>
*{
font-family: PixelFont-7,monospace!important;
}
#helpCameraSettings {
background: #eceeee;
border: 1px solid #42464b;
border-radius: 6px;
margin: 10px auto 0;
margin: 25px auto 0;
width: 400px;
height: 370px;
pointer-events: auto;
max-height: calc(48vh - 50px);
max-width: 48vw;
overflow: hidden;
overflow-y: scroll;
}
#helpCameraSettings h1 {
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
@ -21,18 +26,6 @@
text-align: center;
text-shadow: 0 -1px 0 rgba(0,0,0,0.2), 0 1px 0 #fff;
}
#helpCameraSettings input {
font-size: 70%;
background: linear-gradient(top, #d6d7d7, #dee0e0);
border: 1px solid #a1a3a3;
border-radius: 4px;
box-shadow: 0 1px #fff;
box-sizing: border-box;
color: #696969;
height: 30px;
transition: box-shadow 0.3s;
width: 100%;
}
#helpCameraSettings section {
margin: 10px;
}
@ -41,7 +34,7 @@
margin: 0;
}
#helpCameraSettings button {
margin-top: 10px;
margin: 10px 4px;
background-color: black;
color: white;
border-radius: 7px;
@ -52,9 +45,8 @@
color: #292929;
}
#helpCameraSettings section a{
text-align: center;
font-size: 12px;
margin: 0 6px;
text-decoration: underline;
color: black;
}
#helpCameraSettings section h6,
@ -68,6 +60,9 @@
font-size: 8px;
margin: 0px 20px;
}
#helpCameraSettings section p a{
font-size: 8px;
}
#helpCameraSettings section p.err{
color: #ff0000;
}
@ -82,6 +77,12 @@
width: 200px;
margin-top: 10px;
}
@media only screen and (max-width: 800px),
only screen and (max-height: 600px) {
#helpCameraSettings{
overflow-y: scroll;
}
}
</style>
<form id="helpCameraSettings" hidden>
@ -97,8 +98,12 @@
<p>If you prefer to continue without allowing camera and microphone access, click on Continue</p>
<p id='browserHelpSetting'></p>
</section>
<!--<section class="text-center">
<p>If your problem persist, please contact us: <a id="mailto" href="mailto:workadventure@thecodingmachine.com?subject=Support camera and microphone settings" target="_blank"> workadventure@thecodingmachine.com</a>.</p>
</section>-->
</section>
<section class="action">
<button type="submit" id="helpCameraSettingsFormRefresh">Refresh</button>
<a href="#" id="helpCameraSettingsFormRefresh">Refresh</a>
<button type="submit" id="helpCameraSettingsFormContinue">Continue</button>
</section>
</form>

View File

@ -0,0 +1,120 @@
<style>
*{
font-family: PixelFont-7,monospace!important;
}
#loginScene {
background: #000000;
/*border: 1px solid #ebeeee;*/
border-radius: 6px;
margin: 20px auto 0;
width: 90%;
max-width: 200px;
color: #ebeeee;
max-height: 40vh;
overflow: hidden;
}
#loginScene h1 {
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
border-bottom: 1px solid #a6abaf;
border-radius: 6px 6px 0 0;
box-sizing: border-box;
color: #727678;
display: block;
height: 43px;
padding-top: 10px;
margin: 0;
text-align: center;
text-shadow: 0 -1px 0 rgba(0,0,0,0.2), 0 1px 0 #fff;
}
#loginScene input {
font-size: 70%;
background: linear-gradient(top, #d6d7d7, #dee0e0);
border: 1px solid #a1a3a3;
border-radius: 4px;
box-shadow: 0 1px #fff;
box-sizing: border-box;
color: #696969;
height: 30px;
transition: box-shadow 0.3s;
width: 100%;
text-align: center;
}
#loginScene section {
margin: 10px;
}
#loginScene section.action{
text-align: center;
margin: 0;
}
#loginScene button {
margin: 10px;
background-color: black;;
color: #ebeeee;
border-radius: 7px;
padding-bottom: 4px;
width: 100px;
}
#loginScene button#loginSceneFormCancel {
background-color: #c7c7c700;
color: #292929;
}
#loginScene section h6,
#loginScene section h5{
margin: 1px;
}
#loginScene section.text-center{
text-align: center;
}
#loginScene section a{
font-size: 8px;
text-decoration: underline;
color: #ebeeee;
}
#loginScene section a:hover{
font-weight: 700;
}
#loginScene section p{
text-align: left;
font-size: 8px;
margin: 10px 10px;
}
#loginScene section p.err{
color: red;
text-align: center;
}
#loginScene section p.info{
display: none;
text-align: center;
}
#loginScene section input#loginSceneLink{
background-color: #a1a3a3;
}
#loginScene section img{
width: 160px;
margin: 20px 0;
}
@media only screen and (max-width: 800px),
only screen and (max-height: 600px) {
#loginScene{
overflow-y: scroll;
}
}
</style>
<form id="loginScene" hidden>
<section class="text-center">
<img src="resources/logos/logo.png">
</section>
<section class="text-center">
<h5>Enter your name</h5>
<p class="info">9 chars maximum</p>
<p class="err" id="errorLoginScene"></p>
</section>
<section>
<input type="text" name="email" id="loginSceneName">
<p>By continuing, you are agreeing our <a href="https://workadventu.re/terms-of-use" target="_blank">terms of use</a>, <a href="https://workadventu.re/privacy-policy" target="_blank">privacy policy</a> and <a href="https://workadventu.re/cookie-policy" target="_blank">cookie policy</a>.</p>
</section>
<section class="action">
<button type="submit" id="loginSceneFormSubmit">Continue</button>
</section>
</form>

View File

@ -0,0 +1,142 @@
<style>
*{
font-family: PixelFont-7,monospace!important;
}
#selectCharacterScene {
background: #0000;
/*border: 1px solid #ebeeee;*/
border-radius: 6px;
margin: 10px auto 0;
color: #ebeeee;
max-height: 48vh;
max-width: 300px;
width: 40vw;
overflow: hidden;
}
#selectCharacterScene h1 {
background-image: linear-gradient(top, #f1f3f3, #d4dae0);
border-bottom: 1px solid #a6abaf;
border-radius: 6px 6px 0 0;
box-sizing: border-box;
color: #727678;
display: block;
height: 43px;
padding-top: 10px;
margin: 0;
text-align: center;
text-shadow: 0 -1px 0 rgba(0,0,0,0.2), 0 1px 0 #fff;
}
#selectCharacterScene input {
font-size: 70%;
background: linear-gradient(top, #d6d7d7, #dee0e0);
border: 1px solid #a1a3a3;
border-radius: 4px;
box-shadow: 0 1px #fff;
box-sizing: border-box;
color: #696969;
height: 30px;
transition: box-shadow 0.3s;
width: 100%;
text-align: center;
}
#selectCharacterScene section {
margin: 10px;
}
#selectCharacterScene section.action {
text-align: center;
margin: 0;
margin-top: 28vh;
}
#selectCharacterScene button {
margin: 10px 0px;
background-color: black;;
color: #ebeeee;
border-radius: 7px;
padding-bottom: 4px;
width: 100px;
}
#selectCharacterScene button#selectCharacterSceneFormCancel {
background-color: #aca6a600;
color: #292929;
}
#selectCharacterScene section h6,
#selectCharacterScene section h5{
margin: 1px;
}
#selectCharacterScene section.text-center{
text-align: center;
}
#selectCharacterScene section a{
font-size: 8px;
text-decoration: underline;
color: #ebeeee;
}
#selectCharacterScene section a:hover{
font-weight: 700;
}
#selectCharacterScene section p{
text-align: left;
font-size: 8px;
margin: 10px 10px;
}
#selectCharacterScene section p.err{
color: red;
text-align: center;
}
#selectCharacterScene section p.info{
display: none;
text-align: center;
}
#selectCharacterScene section input#selectCharacterSceneLink{
background-color: #a1a3a3;
}
#selectCharacterScene section img{
width: 160px;
margin: 20px 0;
}
#selectCharacterScene section button.selectCharacterButton{
position: absolute;
top: 20vh;
margin: 0;
width: 25px;
}
#selectCharacterScene section button.selectCharacterButton#selectCharacterButtonLeft{
display: none;
left: 1vw;
}
#selectCharacterScene section button.selectCharacterButton#selectCharacterButtonRight{
display: none;
right: 1vw;
}
#selectCharacterScene section button#selectCharacterSceneFormCustomYourOwnSubmit{
font-size: 14px;
width: auto;
margin-top: -2px;
background-color: #ffd700;
color: black;
}
@media only screen and (max-width: 800px),
only screen and (max-height: 600px) {
#selectCharacterScene{
overflow-y: scroll;
}
#selectCharacterScene section button.selectCharacterButton#selectCharacterButtonRight{
display: block;
}
#selectCharacterScene section button.selectCharacterButton#selectCharacterButtonLeft{
display: block;
}
}
</style>
<form id="selectCharacterScene" hidden>
<section class="text-center">
<h5>Select your WOKA</h5>
<button class="selectCharacterButton" id="selectCharacterButtonLeft"> < </button>
<button class="selectCharacterButton" id="selectCharacterButtonRight"> > </button>
</section>
<section class="action">
<button type="submit" id="selectCharacterSceneFormSubmit">Continue</button>
<button type="submit" id="selectCharacterSceneFormCustomYourOwnSubmit">Custom your WOKA</button>
</section>
</form>

View File

@ -1,4 +1,7 @@
<style>
*{
font-family: PixelFont-7,monospace!important;
}
#warningMain {
border-radius: 5px;
height: 100px;

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg id="i-fullscreen-exit" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none" stroke="#FFF" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M4 12 L12 12 12 4 M20 4 L20 12 28 12 M4 20 L12 20 12 28 M28 20 L20 20 20 28" />
</svg>

After

Width:  |  Height:  |  Size: 329 B

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg id="i-fullscreen" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M4 12 L4 4 12 4 M20 4 L28 4 28 12 M4 20 L4 28 12 28 M28 20 L28 28 20 28" />
</svg>

After

Width:  |  Height:  |  Size: 322 B

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="196" height="196" style="enable-background:new 0 0 196 196;">
<circle cx="98" cy="98" r="98" fill="#808080"/>
<circle cx="98" cy="98" r="78" fill="#fff"/>
<circle cx="98" cy="98" r="55" fill="#808080"/>
<circle cx="98" cy="98" r="30" fill="#fff"/>
<rect width="31" height="25" x="123" y="85" fill="#fff"/>
<rect width="20.5" height="100" transform="matrix(1,1,-1,1,137.75,37.75)" fill="#fff"/>
<rect width="17.5" height="120" transform="matrix(1,1,-1,1,149.25,29.25)" fill="#808080"/>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="196" height="196" style="enable-background:new 0 0 196 196;">
<circle cx="98" cy="98" r="98" fill="#808080"/>
<circle cx="98" cy="98" r="78" fill="#fff"/>
<circle cx="98" cy="98" r="55" fill="#808080"/>
<circle cx="98" cy="98" r="30" fill="#fff"/>
<rect width="31" height="25" x="123" y="85" fill="#fff"/>
<rect width="20.5" height="100" transform="matrix(1,1,-1,1,137.75,37.75)" fill="#fff"/>
<rect width="17.5" height="120" transform="matrix(1,1,-1,1,149.25,29.25)" fill="#808080"/>
</svg>

Before

Width:  |  Height:  |  Size: 586 B

After

Width:  |  Height:  |  Size: 577 B

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="197" height="197" style="enable-background:new 0 0 197 197;">
<circle cx="98" cy="98" r="88" fill="#fff" stroke="#0FAD2C" stroke-width="20"/>
<path d="M152.5,111.4a55.3,55.3 0 1 1 0-25h-26a30,30 0 1 0 0,25z" fill="#0FAD2C"/>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="197" height="197" style="enable-background:new 0 0 197 197;">
<circle cx="98" cy="98" r="88" fill="#fff" stroke="#0FAD2C" stroke-width="20"/>
<path d="M152.5,111.4a55.3,55.3 0 1 1 0-25h-26a30,30 0 1 0 0,25z" fill="#0FAD2C"/>
</svg>

Before

Width:  |  Height:  |  Size: 321 B

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1,44 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 480" style="enable-background:new 0 0 512 480;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<g>
<path class="st0" d="M411.1,384.2c-12.2,0-24.3,0-36.5,0C259.6,257.6,144.5,130.9,29.5,4.3c11.4-0.8,22.9-1.6,34.3-2.4
C179.6,129.3,295.3,256.8,411.1,384.2z"/>
<g>
<path class="st0" d="M352,152.5c-8.8-8.7-34.2-31.6-74.5-38.1c-32.3-5.2-58.1,2.7-70,7.3C170.9,81.5,134.3,41.3,97.8,1
C220.4,1,343,1,465.6,1C427.7,51.5,389.8,102,352,152.5z"/>
<path class="st0" d="M511.5,338.3c0,4.7-0.8,12.2-4.7,20.2c-1.2,2.4-3.4,6.3-7.1,10.5c-4,4.4-7.9,7.1-10.2,8.5
c-5.6,3.5-10.7,4.9-13.5,5.6c-3.8,0.9-6.7,1-10.2,1.2c-3.6,0.2-5.3,0-13.1,0c-3,0-5.4,0-7,0C414.5,307,383.2,229.8,352,152.5
C402.9,62.7,448.7,1,465.6,1c7.5,0,14.3,2.3,14.3,2.3c14.5,4.8,22.3,15.8,23.6,17.8c7.4,10.8,8,21.7,8,25.9
C511.5,144.1,511.5,241.2,511.5,338.3z"/>
<path class="st0" d="M312.5,192c-5.2-5.2-15.6-14.1-31.4-19.4c-12.8-4.2-24-4.3-30.9-3.8c-6.2-7.1-12.4-14.2-18.6-21.3
c10.3-2.4,36.5-6.8,65.1,5.3c15.3,6.5,26.1,15.5,32.7,22.2C323.7,180.8,318.1,186.4,312.5,192z"/>
<path class="st0" d="M329.4,175.1c38.8,69.7,77.6,139.4,116.4,209.1c-50.3-55.4-100.6-110.8-151-166.2c6.9,2.9,14.9,0.7,19.2-5.2
c4.6-6.2,4-15.1-1.6-20.8C318.1,186.4,323.7,180.8,329.4,175.1z"/>
<path class="st0" d="M445.8,384.2L445.8,384.2c-38.8-69.7-77.6-139.4-116.4-209.1c5.3,4.9,12.9,6,18.9,2.7
c7.8-4.2,8.3-13.4,8.3-13.8C386.4,237.4,416.1,310.8,445.8,384.2z"/>
</g>
<path class="st0" d="M162.2,150.4C108.3,213,54.4,275.7,0.5,338.3c0-97.1,0-194.3,0-291.4c0-4,0.6-15.1,8.1-26
C16,10.2,25.7,5.8,29.5,4.3C73.7,53,118,101.7,162.2,150.4z"/>
<path class="st0" d="M199.5,192c-5.3-6-10.6-12-15.8-18C122.6,228.8,61.6,283.6,0.5,338.3c0,4.1,0.6,15.5,8.6,26.7
c1.7,2.4,9.6,12.9,24.1,17.2c5.3,1.6,10,1.9,13.1,1.9C97.5,320.2,148.5,256.1,199.5,192z"/>
<path class="st0" d="M84.7,384.2c-12.7,0-25.5,0-38.2,0c58.2-56.2,116.5-112.5,174.7-168.7c8.3,9.1,16.6,18.2,24.9,27.2
c-2.2,1.1-5.5,3-8.4,6.4c-3.1,3.7-4.2,7.3-4.4,7.8C231.3,262.4,194.5,295.2,84.7,384.2z"/>
<path class="st0" d="M46.4,384.2c-15.3-15.3-30.6-30.6-45.9-45.9C52.8,277.5,105.1,216.8,157.4,156c-3.7,6.7-2.2,15.1,3.5,20
c5.4,4.6,13.3,5.1,19.4,1C135.7,246.1,91.1,315.1,46.4,384.2z"/>
<path class="st0" d="M49.6,384.3c-1.1,0-2.1,0-3.2-0.1c50.1-62.9,100.2-125.8,150.3-188.7c-3.5,6.6-2.1,14.8,3.4,19.7
c5.8,5.2,14.8,5.3,21,0.3C164,271.7,106.8,328,49.6,384.3z"/>
<path class="st0" d="M374.6,384.2c-96.6,0-193.3,0-289.9,0C16.5,308,1.3,223,28.5,194.5C57,164.7,150.6,177,233.3,256.9
c-3.9,11.8,2,24.8,13.3,29.6c11,4.7,24,0.4,30.2-10C309.3,312.4,342,348.3,374.6,384.2z"/>
<path class="st0" d="M219.7,226.7"/>
<path class="st0" d="M368.9,480c-74.9,0-149.8,0-224.7,0c-8.8,0-16-7.2-16-16c0-8.8,7.2-16,16-16c74.9,0,149.9,0,224.8,0.1
c8.3,0.7,14.7,7.6,14.7,15.9C383.7,472.3,377.2,479.3,368.9,480z"/>
<rect x="208.1" y="384.2" class="st0" width="31.9" height="63.9"/>
<rect x="272" y="384.2" class="st0" width="32" height="63.9"/>
<path class="st0" d="M410.3,395.5"/>
</g>
</svg>
<svg id="Capa_1" data-name="Capa 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 469.33 426.67"><defs><style>.cls-1{fill:#fff;}</style></defs><path class="cls-1" d="M426.67,21.33h-384A42.66,42.66,0,0,0,0,64V320a42.66,42.66,0,0,0,42.67,42.67H192v42.66H149.33V448H320V405.33H277.33V362.67H426.67A42.66,42.66,0,0,0,469.33,320V64A42.66,42.66,0,0,0,426.67,21.33Zm0,298.67h-384V64h384Z" transform="translate(0 -21.33)"/><path class="cls-1" d="M267.2,127.15V86.26a8.14,8.14,0,0,1,14.18-5.44l73.2,81.34a8.12,8.12,0,0,1,.25,10.57l-73.2,89.47a8.14,8.14,0,0,1-14.43-5.13V216.54c-64.25,2.09-104.35,29.55-122.42,83.77a8.13,8.13,0,0,1-15.84-2.58C128.94,202,186.59,131.59,267.2,127.15Zm8.14,73a8.13,8.13,0,0,1,8.13,8.14v26l54.36-66.44-54.36-60.39v27.6a8.13,8.13,0,0,1-8.13,8.14c-63.93,0-111.77,44.24-125.87,111.73C175.65,218.53,217.8,200.13,275.34,200.13Z" transform="translate(0 -21.33)"/></svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 884 B

View File

@ -1,15 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 480" style="enable-background:new 0 0 512 480;" xml:space="preserve">
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 469.3 469.3" style="enable-background:new 0 0 469.3 469.3;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{opacity:0.9;fill:#FFFFFF;stroke:#FFFFFF;stroke-width:15;stroke-miterlimit:10;enable-background:new ;}
</style>
<path class="st0" d="M466,0H46C20.6,0,0,20.6,0,46v292c0,25.4,20.6,46,46,46h162v64h-64c-8.8,0-16,7.2-16,16s7.2,16,16,16h224
c8.8,0,16-7.2,16-16s-7.2-16-16-16h-64v-64h162c25.4,0,46-20.6,46-46V46C512,20.6,491.4,0,466,0z M232,264c0-13.3,10.7-24,24-24
c13.3,0,24,10.7,24,24s-10.7,24-24,24C242.7,288,232,277.3,232,264z M272,448h-32v-64h32V448z M312.6,214.1
c-6.2,6.2-16.4,6.2-22.6,0c-18.7-18.8-49.1-18.8-67.9,0c0,0,0,0,0,0c-6.4,6.1-16.5,5.8-22.6-0.6c-5.9-6.2-5.9-15.9,0-22
c31.2-31.2,81.9-31.2,113.1,0c0,0,0,0,0,0C318.8,197.7,318.8,207.8,312.6,214.1z M352.2,174.5c-6.2,6.2-16.4,6.3-22.6,0c0,0,0,0,0,0
c-40.6-40.6-106.4-40.6-147.1,0c-6.2,6.3-16.4,6.3-22.6,0c-6.3-6.2-6.3-16.4,0-22.6c53.1-53.1,139.2-53.1,192.3,0c0,0,0,0,0,0
C358.4,158.1,358.4,168.2,352.2,174.5C352.2,174.5,352.2,174.5,352.2,174.5L352.2,174.5z"/>
<g>
<g>
<path class="st0" d="M426.7,21.3h-384C19.1,21.3,0,40.4,0,64v256c0,23.6,19.1,42.7,42.7,42.7H192v42.7h-42.7V448H320v-42.7h-42.7
v-42.7h149.3c23.6,0,42.7-19.1,42.7-42.7V64C469.3,40.4,450.2,21.3,426.7,21.3z M426.7,320h-384V64h384V320z"/>
</g>
</g>
<g>
<g>
<path class="st0" d="M267.2,127.2V86.3c0-4.5,3.6-8.1,8.1-8.1c2.3,0,4.5,1,6,2.7l73.2,81.3c2.7,3,2.8,7.5,0.3,10.6l-73.2,89.5
c-2.8,3.5-8,4-11.4,1.1c-1.9-1.5-3-3.8-3-6.3v-40.5c-64.3,2.1-104.4,29.6-122.4,83.8c-1.1,3.3-4.2,5.6-7.7,5.6
c-0.4,0-0.9,0-1.3-0.1c-3.9-0.6-6.8-4-6.8-8C128.9,202,186.6,131.6,267.2,127.2z M275.3,200.1c4.5,0,8.1,3.6,8.1,8.1v26l54.4-66.4
l-54.4-60.4V135c0,4.5-3.6,8.1-8.1,8.1c-63.9,0-111.8,44.2-125.9,111.7C175.6,218.5,217.8,200.1,275.3,200.1z"/>
</g>
</g>
<path class="st1" d="M13.4,42.7C153.6,142.3,293.8,241.9,434,341.5"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 969 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -1,170 +0,0 @@
/* A potentially shared website could appear in an iframe in the cowebsite space. */
#cowebsite {
position: fixed;
transition: transform 0.5s;
background-color: white;
&.loading {
background-color: gray;
}
main {
iframe {
width: 100%;
height: 100%;
}
}
aside {
background: gray;
align-items: center;
display: flex;
img {
margin: 3px;
pointer-events: none;
height: 20px;
}
}
.top-right-btn{
position: absolute;
background: none;
border: none;
cursor: url('/resources/logos/cursor_pointer.png'), pointer;
img {
height: 20px;
background-color: rgba(0,0.0,0,0.3);
padding: 5px;
border-radius: 3px;
}
img:hover {
background-color: rgba(0,0,0,0.4);
}
}
}
@media (min-aspect-ratio: 1/1) {
#cowebsite {
right: 0;
top: 0;
width: 50%;
height: 100vh;
display: flex;
&.loading {
transform: translateX(90%);
}
&.hidden {
transform: translateX(100%);
}
main {
width: 100%;
}
aside {
width: 30px;
cursor: ew-resize;
img {
cursor: ew-resize;
transform: rotate(90deg);
}
}
.top-right-btn{
top: 10px;
right: -100px;
animation: right .2s ease;
img {
right: 15px;
}
}
#cowebsite-close {
right: -140px;
}
#cowebsite-fullscreen {
right: -100px;
}
}
#cowebsite:hover {
#cowebsite-close{
right: 10px;
}
#cowebsite-fullscreen{
right: 45px;
}
}
}
@media (max-aspect-ratio: 1/1) {
#cowebsite {
left: 0;
bottom: 0;
width: 100%;
height: 50%;
display: flex;
flex-direction: column;
&.loading {
transform: translateY(90%);
}
&.hidden {
transform: translateY(100%);
}
main {
height: 100%;
}
aside {
height: 30px;
cursor: ns-resize;
flex-direction: column;
img {
cursor: ns-resize;
}
}
.top-right-btn{
top: 10px;
right: -100px;
animation: right .2s ease;
img {
right: 15px;
}
}
#cowebsite-close {
right: -140px;
}
#cowebsite-fullscreen {
right: -100px;
}
}
#cowebsite:hover {
#cowebsite-close{
right: 10px;
}
#cowebsite-fullscreen{
right: 45px;
}
}
}

View File

@ -1,2 +0,0 @@
@import "cowebsite.scss";
@import "style.css";

View File

@ -1,41 +1,149 @@
{
"name": "App",
"icons": [
{
"src": "\/android-icon-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "0.75"
},
{
"src": "\/android-icon-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1.0"
},
{
"src": "\/android-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "\/android-icon-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "\/android-icon-144x144.png",
"sizes": "144x144",
"type": "image\/png",
"density": "3.0"
},
{
"src": "\/android-icon-192x192.png",
"sizes": "192x192",
"type": "image\/png",
"density": "4.0"
}
]
"short_name": "WA",
"name": "WorkAdventure",
"icons": [
{
"src": "/static/images/favicons/apple-icon-57x57.png",
"sizes": "57x57",
"type": "image\/png"
},
{
"src": "/static/images/favicons/apple-icon-60x60.png",
"sizes": "60x60",
"type": "image\/png"
},
{
"src": "/static/images/favicons/apple-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png"
},
{
"src": "/static/images/favicons/apple-icon-76x76.png",
"sizes": "76x76",
"type": "image\/png"
},
{
"src": "/static/images/favicons/apple-icon-114x114.png",
"sizes": "114x114",
"type": "image\/png"
},
{
"src": "/static/images/favicons/apple-icon-120x120.png",
"sizes": "120x120",
"type": "image\/png"
},
{
"src": "/static/images/favicons/apple-icon-144x144.png",
"sizes": "144x144",
"type": "image\/png"
},
{
"src": "/static/images/favicons/apple-icon-152x152.png",
"sizes": "152x152",
"type": "image\/png"
},
{
"src": "/static/images/favicons/apple-icon-180x180.png",
"sizes": "180x180",
"type": "image\/png"
},
{
"src": "/static/images/favicons/android-icon-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "0.75"
},
{
"src": "/static/images/favicons/android-icon-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1.0"
},
{
"src": "/static/images/favicons/android-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "/static/images/favicons/favicon-16x16.png",
"sizes": "16x16",
"type": "image\/png",
"density": "1"
},
{
"src": "/static/images/favicons/favicon-32x32.png",
"sizes": "32x32",
"type": "image\/png",
"density": "1.5"
},
{
"src": "/static/images/favicons/favicon-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "/static/images/favicons/android-icon-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "1"
},
{
"src": "/static/images/favicons/android-icon-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1"
},
{
"src": "/static/images/favicons/android-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "/static/images/favicons/android-icon-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "/static/images/favicons/android-icon-144x144.png",
"sizes": "144x144",
"type": "image\/png",
"density": "3.0"
},
{
"src": "/static/images/favicons/android-icon-192x192.png",
"sizes": "192x192",
"type": "image\/png",
"density": "4.0"
}
],
"start_url": "/",
"background_color": "#000000",
"display_override": ["window-control-overlay", "minimal-ui"],
"display": "standalone",
"scope": "/",
"theme_color": "#000000",
"shortcuts": [
{
"name": "WorkAdventures",
"short_name": "WA",
"description": "WorkAdventure application",
"url": "/",
"icons": [{ "src": "/static/images/favicons/android-icon-192x192.png", "sizes": "192x192" }]
}
],
"description": "WorkAdventure application",
"screenshots": [],
"related_applications": [{
"platform": "web",
"url": "https://workadventu.re"
}, {
"platform": "play",
"url": "https://play.workadventu.re"
}]
}

View File

@ -4,44 +4,55 @@
"main": "index.js",
"license": "SEE LICENSE IN LICENSE.txt",
"devDependencies": {
"@tsconfig/svelte": "^1.0.10",
"@types/google-protobuf": "^3.7.3",
"@types/jasmine": "^3.5.10",
"@types/mini-css-extract-plugin": "^1.4.3",
"@types/node": "^15.3.0",
"@types/quill": "^1.3.7",
"@typescript-eslint/eslint-plugin": "^2.26.0",
"@typescript-eslint/parser": "^2.26.0",
"css-loader": "^5.1.3",
"eslint": "^6.8.0",
"html-webpack-plugin": "^4.3.0",
"@types/webpack-dev-server": "^3.11.4",
"@typescript-eslint/eslint-plugin": "^4.23.0",
"@typescript-eslint/parser": "^4.23.0",
"css-loader": "^5.2.4",
"eslint": "^7.26.0",
"fork-ts-checker-webpack-plugin": "^6.2.9",
"html-webpack-plugin": "^5.3.1",
"jasmine": "^3.5.0",
"mini-css-extract-plugin": "^1.3.9",
"sass": "^1.32.8",
"sass-loader": "10.1.1",
"ts-loader": "^6.2.2",
"ts-node": "^8.10.2",
"typescript": "^3.8.3",
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3",
"webpack-merge": "^4.2.2"
"mini-css-extract-plugin": "^1.6.0",
"node-polyfill-webpack-plugin": "^1.1.2",
"sass": "^1.32.12",
"sass-loader": "^11.1.0",
"svelte": "^3.38.2",
"svelte-loader": "^3.1.1",
"svelte-preprocess": "^4.7.3",
"ts-loader": "^9.1.2",
"ts-node": "^9.1.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.2.4",
"webpack": "^5.37.0",
"webpack-cli": "^4.7.0",
"webpack-dev-server": "^3.11.2"
},
"dependencies": {
"@types/hls.js": "^0.13.3",
"@types/simple-peer": "^9.6.0",
"@types/socket.io-client": "^1.4.32",
"axios": "^0.21.1",
"generic-type-guard": "^3.2.0",
"google-protobuf": "^3.13.0",
"phaser": "^3.53.1",
"phaser": "^3.54.0",
"hls.js": "^0.14.17",
"phaser3-rex-plugins": "^1.1.42",
"queue-typescript": "^1.0.1",
"quill": "^1.3.7",
"quill": "1.3.6",
"rxjs": "^6.6.3",
"simple-peer": "^9.6.2",
"socket.io-client": "^2.3.0",
"webpack-require-http": "^0.4.3"
"socket.io-client": "^2.3.0"
},
"scripts": {
"start": "webpack-dev-server --open",
"build": "webpack --config webpack.prod.js",
"test": "ts-node node_modules/jasmine/bin/jasmine --config=jasmine.json",
"start": "TS_NODE_PROJECT=\"tsconfig-for-webpack.json\" webpack serve --open",
"build": "TS_NODE_PROJECT=\"tsconfig-for-webpack.json\" NODE_ENV=production webpack",
"test": "TS_NODE_PROJECT=\"tsconfig-for-jasmine.json\" ts-node node_modules/jasmine/bin/jasmine --config=jasmine.json",
"lint": "node_modules/.bin/eslint src/ . --ext .ts",
"fix": "node_modules/.bin/eslint --fix src/ . --ext .ts"
}

View File

@ -0,0 +1 @@
iframe_api.d.ts

View File

@ -0,0 +1,27 @@
<h1 align="center">WorkAdventure - IFrame API typings for Typescript</h1>
<p align="center">This package contains Typescript typings for <a href="https://workadventu.re/map-building/scripting">WorkAdventure's map scripting API</a></p>
<hr/>
[WorkAdventure](https://workadventu.re) comes with a scripting API. Using this API, you can add some intelligence to your map.
You use this API by loading an external script directly from WorkAdventure (at https://play.workadventu.re/iframe_api.js), or this script is loaded
for you if you are using the "script" property of a map.
This project contains Typescript typings for the `WA` object provided by this script.
## Usage
This package is only useful if you are using Typescript to script your WorkAdventure maps.
## Download & Installation
```shell
$ npm install @workadventure/iframe-api-typings
```
or
```shell
$ yarn add @workadventure/iframe-api-typings
```

View File

@ -0,0 +1 @@
// This file is voluntarily empty.

View File

@ -0,0 +1,13 @@
{
"name": "@workadventure/iframe-api-typings",
"version": "VERSION_PLACEHOLDER",
"description": "Typescript typings for WorkAdventure iFrame API",
"main": "iframe_api.js",
"types": "iframe_api.d.ts",
"repository": "https://github.com/thecodingmachine/workadventure/",
"author": "David Négrier <d.negrier@thecodingmachine.com>",
"license": "MIT",
"publishConfig": {
"access": "public"
}
}

View File

@ -1,8 +1,7 @@
import {HtmlUtils} from "../WebRtc/HtmlUtils";
import {UserInputManager} from "../Phaser/UserInput/UserInputManager";
import {RoomConnection} from "../Connexion/RoomConnection";
import {PlayGlobalMessageInterface} from "../Connexion/ConnexionModels";
import {ADMIN_URL} from "../Enum/EnvironmentVariable";
import type {UserInputManager} from "../Phaser/UserInput/UserInputManager";
import type {RoomConnection} from "../Connexion/RoomConnection";
import type {PlayGlobalMessageInterface} from "../Connexion/ConnexionModels";
import {AdminMessageEventTypes} from "../Connexion/AdminMessagesService";
export const CLASS_CONSOLE_MESSAGE = 'main-console';
@ -162,42 +161,42 @@ export class ConsoleGlobalMessageManager {
this.divMessageConsole.appendChild(section);
(async () => {
// Start loading CSS
const cssPromise = ConsoleGlobalMessageManager.loadCss();
// Import quill
const Quill:any = await import("quill"); // eslint-disable-line @typescript-eslint/no-explicit-any
// Wait for CSS to be loaded
await cssPromise;
try{
// Import quill
const {default: Quill}:any = await import("quill"); // eslint-disable-line @typescript-eslint/no-explicit-any
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{'header': 1}, {'header': 2}], // custom button values
[{'list': 'ordered'}, {'list': 'bullet'}],
[{'script': 'sub'}, {'script': 'super'}], // superscript/subscript
[{'indent': '-1'}, {'indent': '+1'}], // outdent/indent
[{'direction': 'rtl'}], // text direction
[{'header': 1}, {'header': 2}], // custom button values
[{'list': 'ordered'}, {'list': 'bullet'}],
[{'script': 'sub'}, {'script': 'super'}], // superscript/subscript
[{'indent': '-1'}, {'indent': '+1'}], // outdent/indent
[{'direction': 'rtl'}], // text direction
[{'size': ['small', false, 'large', 'huge']}], // custom dropdown
[{'header': [1, 2, 3, 4, 5, 6, false]}],
[{'size': ['small', false, 'large', 'huge']}], // custom dropdown
[{'header': [1, 2, 3, 4, 5, 6, false]}],
[{'color': []}, {'background': []}], // dropdown with defaults from theme
[{'font': []}],
[{'align': []}],
[{'color': []}, {'background': []}], // dropdown with defaults from theme
[{'font': []}],
[{'align': []}],
['clean'],
['clean'],
['link', 'image', 'video']
// remove formatting button
];
['link', 'image', 'video']
// remove formatting button
];
new Quill(`#${INPUT_CONSOLE_MESSAGE}`, {
theme: 'snow',
modules: {
toolbar: toolbarOptions
},
});
new Quill(`#${INPUT_CONSOLE_MESSAGE}`, {
theme: 'snow',
modules: {
toolbar: toolbarOptions
},
});
}catch(err){
console.error(err);
}
})();
}
@ -263,27 +262,6 @@ export class ConsoleGlobalMessageManager {
this.divMessageConsole.appendChild(section);
}
private static loadCss(): Promise<void> {
return new Promise<void>((resolve, reject) => {
if (ConsoleGlobalMessageManager.cssLoaded) {
resolve();
return;
}
const fileref = document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", "https://cdn.quilljs.com/1.3.7/quill.snow.css");
document.getElementsByTagName("head")[0].appendChild(fileref);
ConsoleGlobalMessageManager.cssLoaded = true;
fileref.onload = () => {
resolve();
}
fileref.onerror = () => {
reject();
}
});
}
sendMessage(){
const inputType = HtmlUtils.getElementByIdOrFail<HTMLInputElement>(INPUT_TYPE_CONSOLE);
if(AUDIO_TYPE !== inputType.value && MESSAGE_TYPE !== inputType.value){
@ -336,7 +314,7 @@ export class ConsoleGlobalMessageManager {
}
active(){
this.userInputManager.clearAllKeys();
this.userInputManager.disableControls();
this.divMainConsole.style.top = '0';
this.activeConsole = true;
}

View File

@ -1,8 +1,8 @@
import {HtmlUtils} from "./../WebRtc/HtmlUtils";
import {AUDIO_TYPE, MESSAGE_TYPE} from "./ConsoleGlobalMessageManager";
import {API_URL, UPLOADER_URL} from "../Enum/EnvironmentVariable";
import {RoomConnection} from "../Connexion/RoomConnection";
import {PlayGlobalMessageInterface} from "../Connexion/ConnexionModels";
import {PUSHER_URL, UPLOADER_URL} from "../Enum/EnvironmentVariable";
import type {RoomConnection} from "../Connexion/RoomConnection";
import type {PlayGlobalMessageInterface} from "../Connexion/ConnexionModels";
export class GlobalMessageManager {

View File

@ -1,4 +1,4 @@
import {TypeMessageInterface} from "./UserMessageManager";
import type {TypeMessageInterface} from "./UserMessageManager";
import {HtmlUtils} from "../WebRtc/HtmlUtils";
let modalTimeOut : NodeJS.Timeout;
@ -86,4 +86,4 @@ export class Banned extends TypeMessageExt {
showMessage(message: string){
super.showMessage(message, false);
}
}
}

View File

@ -0,0 +1,11 @@
import * as tg from "generic-type-guard";
export const isButtonClickedEvent =
new tg.IsInterface().withProperties({
popupId: tg.isNumber,
buttonId: tg.isNumber,
}).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 ButtonClickedEvent = tg.GuardedType<typeof isButtonClickedEvent>;

View File

@ -0,0 +1,11 @@
import * as tg from "generic-type-guard";
export const isChatEvent =
new tg.IsInterface().withProperties({
message: tg.isString,
author: tg.isString,
}).get();
/**
* A message sent from the iFrame to the game to add a message in the chat.
*/
export type ChatEvent = tg.GuardedType<typeof isChatEvent>;

View File

@ -0,0 +1,11 @@
import * as tg from "generic-type-guard";
export const isClosePopupEvent =
new tg.IsInterface().withProperties({
popupId: tg.isNumber,
}).get();
/**
* A message sent from the iFrame to the game to add a message in the chat.
*/
export type ClosePopupEvent = tg.GuardedType<typeof isClosePopupEvent>;

View File

@ -0,0 +1,10 @@
import * as tg from "generic-type-guard";
export const isEnterLeaveEvent =
new tg.IsInterface().withProperties({
name: tg.isString,
}).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 EnterLeaveEvent = tg.GuardedType<typeof isEnterLeaveEvent>;

View File

@ -0,0 +1,13 @@
import * as tg from "generic-type-guard";
export const isGoToPageEvent =
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 GoToPageEvent = tg.GuardedType<typeof isGoToPageEvent>;

View File

@ -0,0 +1,60 @@
import type { ButtonClickedEvent } from './ButtonClickedEvent';
import type { ChatEvent } from './ChatEvent';
import type { ClosePopupEvent } from './ClosePopupEvent';
import type { EnterLeaveEvent } from './EnterLeaveEvent';
import type { GoToPageEvent } from './GoToPageEvent';
import type { OpenCoWebSiteEvent } from './OpenCoWebSiteEvent';
import type { OpenPopupEvent } from './OpenPopupEvent';
import type { OpenTabEvent } from './OpenTabEvent';
import type { UserInputChatEvent } from './UserInputChatEvent';
import type {LoadSoundEvent} from "./LoadSoundEvent";
import type {PlaySoundEvent} from "./PlaySoundEvent";
export interface TypedMessageEvent<T> extends MessageEvent {
data: T
}
export type IframeEventMap = {
//getState: GameStateEvent,
// updateTile: UpdateTileEvent
chat: ChatEvent,
openPopup: OpenPopupEvent
closePopup: ClosePopupEvent
openTab: OpenTabEvent
goToPage: GoToPageEvent
openCoWebSite: OpenCoWebSiteEvent
closeCoWebSite: null
disablePlayerControls: null
restorePlayerControls: null
displayBubble: null
removeBubble: null
loadSound: LoadSoundEvent
playSound: PlaySoundEvent
stopSound: null
}
export interface IframeEvent<T extends keyof IframeEventMap> {
type: T;
data: IframeEventMap[T];
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isIframeEventWrapper = (event: any): event is IframeEvent<keyof IframeEventMap> => typeof event.type === 'string';
export interface IframeResponseEventMap {
userInputChat: UserInputChatEvent
enterEvent: EnterLeaveEvent
leaveEvent: EnterLeaveEvent
buttonClickedEvent: ButtonClickedEvent
// gameState: GameStateEvent
}
export interface IframeResponseEvent<T extends keyof IframeResponseEventMap> {
type: T;
data: IframeResponseEventMap[T];
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isIframeResponseEventWrapper = (event: { type?: string }): event is IframeResponseEvent<keyof IframeResponseEventMap> => typeof event.type === 'string';

View File

@ -0,0 +1,11 @@
import * as tg from "generic-type-guard";
export const isLoadSoundEvent =
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 LoadSoundEvent = tg.GuardedType<typeof isLoadSoundEvent>;

View File

@ -0,0 +1,13 @@
import * as tg from "generic-type-guard";
export const isOpenCoWebsite =
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 OpenCoWebSiteEvent = tg.GuardedType<typeof isOpenCoWebsite>;

View File

@ -0,0 +1,20 @@
import * as tg from "generic-type-guard";
const isButtonDescriptor =
new tg.IsInterface().withProperties({
label: tg.isString,
className: tg.isOptional(tg.isString)
}).get();
export const isOpenPopupEvent =
new tg.IsInterface().withProperties({
popupId: tg.isNumber,
targetObject: tg.isString,
message: tg.isString,
buttons: tg.isArray(isButtonDescriptor)
}).get();
/**
* A message sent from the iFrame to the game to add a message in the chat.
*/
export type OpenPopupEvent = tg.GuardedType<typeof isOpenPopupEvent>;

View File

@ -0,0 +1,13 @@
import * as tg from "generic-type-guard";
export const isOpenTabEvent =
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 OpenTabEvent = tg.GuardedType<typeof isOpenTabEvent>;

View File

@ -0,0 +1,24 @@
import * as tg from "generic-type-guard";
const isSoundConfig =
new tg.IsInterface().withProperties({
volume: tg.isOptional(tg.isNumber),
loop: tg.isOptional(tg.isBoolean),
mute: tg.isOptional(tg.isBoolean),
rate: tg.isOptional(tg.isNumber),
detune: tg.isOptional(tg.isNumber),
seek: tg.isOptional(tg.isNumber),
delay: tg.isOptional(tg.isNumber)
}).get();
export const isPlaySoundEvent =
new tg.IsInterface().withProperties({
url: tg.isString,
config : tg.isOptional(isSoundConfig),
}).get();
/**
* A message sent from the iFrame to the game to add a message in the chat.
*/
export type PlaySoundEvent = tg.GuardedType<typeof isPlaySoundEvent>;

View File

@ -0,0 +1,11 @@
import * as tg from "generic-type-guard";
export const isStopSoundEvent =
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 StopSoundEvent = tg.GuardedType<typeof isStopSoundEvent>;

View File

@ -0,0 +1,10 @@
import * as tg from "generic-type-guard";
export const isUserInputChatEvent =
new tg.IsInterface().withProperties({
message: tg.isString,
}).get();
/**
* A message sent from the game to the iFrame when a user types a message in the chat.
*/
export type UserInputChatEvent = tg.GuardedType<typeof isUserInputChatEvent>;

View File

@ -0,0 +1,267 @@
import { Subject } from "rxjs";
import { ChatEvent, isChatEvent } from "./Events/ChatEvent";
import { HtmlUtils } from "../WebRtc/HtmlUtils";
import type { EnterLeaveEvent } from "./Events/EnterLeaveEvent";
import { isOpenPopupEvent, OpenPopupEvent } from "./Events/OpenPopupEvent";
import { isOpenTabEvent, OpenTabEvent } from "./Events/OpenTabEvent";
import type { ButtonClickedEvent } from "./Events/ButtonClickedEvent";
import { ClosePopupEvent, isClosePopupEvent } from "./Events/ClosePopupEvent";
import { scriptUtils } from "./ScriptUtils";
import { GoToPageEvent, isGoToPageEvent } from "./Events/GoToPageEvent";
import { isOpenCoWebsite, OpenCoWebSiteEvent } from "./Events/OpenCoWebSiteEvent";
import { IframeEventMap, IframeEvent, IframeResponseEvent, IframeResponseEventMap, isIframeEventWrapper, TypedMessageEvent } from "./Events/IframeEvent";
import type { UserInputChatEvent } from "./Events/UserInputChatEvent";
import {isPlaySoundEvent, PlaySoundEvent} from "./Events/PlaySoundEvent";
import {isStopSoundEvent, StopSoundEvent} from "./Events/StopSoundEvent";
import {isLoadSoundEvent, LoadSoundEvent} from "./Events/LoadSoundEvent";
/**
* Listens to messages from iframes and turn those messages into easy to use observables.
* Also allows to send messages to those iframes.
*/
class IframeListener {
private readonly _chatStream: Subject<ChatEvent> = new Subject();
public readonly chatStream = this._chatStream.asObservable();
private readonly _openPopupStream: Subject<OpenPopupEvent> = new Subject();
public readonly openPopupStream = this._openPopupStream.asObservable();
private readonly _openTabStream: Subject<OpenTabEvent> = new Subject();
public readonly openTabStream = this._openTabStream.asObservable();
private readonly _goToPageStream: Subject<GoToPageEvent> = new Subject();
public readonly goToPageStream = this._goToPageStream.asObservable();
private readonly _openCoWebSiteStream: Subject<OpenCoWebSiteEvent> = new Subject();
public readonly openCoWebSiteStream = this._openCoWebSiteStream.asObservable();
private readonly _closeCoWebSiteStream: Subject<void> = new Subject();
public readonly closeCoWebSiteStream = this._closeCoWebSiteStream.asObservable();
private readonly _disablePlayerControlStream: Subject<void> = new Subject();
public readonly disablePlayerControlStream = this._disablePlayerControlStream.asObservable();
private readonly _enablePlayerControlStream: Subject<void> = new Subject();
public readonly enablePlayerControlStream = this._enablePlayerControlStream.asObservable();
private readonly _closePopupStream: Subject<ClosePopupEvent> = new Subject();
public readonly closePopupStream = this._closePopupStream.asObservable();
private readonly _displayBubbleStream: Subject<void> = new Subject();
public readonly displayBubbleStream = this._displayBubbleStream.asObservable();
private readonly _removeBubbleStream: Subject<void> = new Subject();
public readonly removeBubbleStream = this._removeBubbleStream.asObservable();
private readonly _playSoundStream: Subject<PlaySoundEvent> = new Subject();
public readonly playSoundStream = this._playSoundStream.asObservable();
private readonly _stopSoundStream: Subject<StopSoundEvent> = new Subject();
public readonly stopSoundStream = this._stopSoundStream.asObservable();
private readonly _loadSoundStream: Subject<LoadSoundEvent> = new Subject();
public readonly loadSoundStream = this._loadSoundStream.asObservable();
private readonly _unregisterIFrameStream: Subject<void> = new Subject();
public readonly unregisterIFrameStream = this._unregisterIFrameStream.asObservable();
private readonly iframes = new Set<HTMLIFrameElement>();
private readonly scripts = new Map<string, HTMLIFrameElement>();
init() {
window.addEventListener("message", (message: TypedMessageEvent<IframeEvent<keyof IframeEventMap>>) => {
// Do we trust the sender of this message?
// 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) {
if (iframe.contentWindow === message.source) {
foundSrc = iframe.src;
break;
}
}
if (!foundSrc) {
return;
}
const payload = message.data;
if (isIframeEventWrapper(payload)) {
if (payload.type === 'chat' && isChatEvent(payload.data)) {
this._chatStream.next(payload.data);
} else if (payload.type === 'openPopup' && isOpenPopupEvent(payload.data)) {
this._openPopupStream.next(payload.data);
} else if (payload.type === 'closePopup' && isClosePopupEvent(payload.data)) {
this._closePopupStream.next(payload.data);
}
else if (payload.type === 'openTab' && isOpenTabEvent(payload.data)) {
scriptUtils.openTab(payload.data.url);
}
else if (payload.type === 'goToPage' && isGoToPageEvent(payload.data)) {
scriptUtils.goToPage(payload.data.url);
}
else if (payload.type === 'playSound' && isPlaySoundEvent(payload.data)) {
this._playSoundStream.next(payload.data);
}
else if (payload.type === 'stopSound' && isStopSoundEvent(payload.data)) {
this._stopSoundStream.next(payload.data);
}
else if (payload.type === 'loadSound' && isLoadSoundEvent(payload.data)) {
this._loadSoundStream.next(payload.data);
}
else if (payload.type === 'openCoWebSite' && isOpenCoWebsite(payload.data)) {
const scriptUrl = [...this.scripts.keys()].find(key => {
return this.scripts.get(key)?.contentWindow == message.source
})
scriptUtils.openCoWebsite(payload.data.url, scriptUrl || foundSrc);
}
else if (payload.type === 'closeCoWebSite') {
scriptUtils.closeCoWebSite();
}
else if (payload.type === 'disablePlayerControls') {
this._disablePlayerControlStream.next();
}
else if (payload.type === 'restorePlayerControls') {
this._enablePlayerControlStream.next();
}
else if (payload.type === 'displayBubble') {
this._displayBubbleStream.next();
}
else if (payload.type === 'removeBubble') {
this._removeBubbleStream.next();
}
}
}, false);
}
/**
* Allows the passed iFrame to send/receive messages via the API.
*/
registerIframe(iframe: HTMLIFrameElement): void {
this.iframes.add(iframe);
}
unregisterIframe(iframe: HTMLIFrameElement): void {
this._unregisterIFrameStream.next();
this.iframes.delete(iframe);
}
registerScript(scriptUrl: string): void {
console.log('Loading map related script at ', scriptUrl)
if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
// Using external iframe mode (
const iframe = document.createElement('iframe');
iframe.id = this.getIFrameId(scriptUrl);
iframe.style.display = 'none';
iframe.src = '/iframe.html?script=' + encodeURIComponent(scriptUrl);
// We are putting a sandbox on this script because it will run in the same domain as the main website.
iframe.sandbox.add('allow-scripts');
iframe.sandbox.add('allow-top-navigation-by-user-activation');
document.body.prepend(iframe);
this.scripts.set(scriptUrl, iframe);
this.registerIframe(iframe);
} else {
// production code
const iframe = document.createElement('iframe');
iframe.id = this.getIFrameId(scriptUrl);
iframe.style.display = 'none';
// We are putting a sandbox on this script because it will run in the same domain as the main website.
iframe.sandbox.add('allow-scripts');
iframe.sandbox.add('allow-top-navigation-by-user-activation');
const html = '<!doctype html>\n' +
'\n' +
'<html lang="en">\n' +
'<head>\n' +
'<script src="' + window.location.protocol + '//' + window.location.host + '/iframe_api.js" ></script>\n' +
'<script src="' + scriptUrl + '" ></script>\n' +
'</head>\n' +
'</html>\n';
//iframe.src = "data:text/html;charset=utf-8," + escape(html);
iframe.srcdoc = html;
document.body.prepend(iframe);
this.scripts.set(scriptUrl, iframe);
this.registerIframe(iframe);
}
}
private getIFrameId(scriptUrl: string): string {
return 'script' + btoa(scriptUrl);
}
unregisterScript(scriptUrl: string): void {
const iFrameId = this.getIFrameId(scriptUrl);
const iframe = HtmlUtils.getElementByIdOrFail<HTMLIFrameElement>(iFrameId);
if (!iframe) {
throw new Error('Unknown iframe for script "' + scriptUrl + '"');
}
this.unregisterIframe(iframe);
iframe.remove();
this.scripts.delete(scriptUrl);
}
sendUserInputChat(message: string) {
this.postMessage({
'type': 'userInputChat',
'data': {
'message': message,
} as UserInputChatEvent
});
}
sendEnterEvent(name: string) {
this.postMessage({
'type': 'enterEvent',
'data': {
"name": name
} as EnterLeaveEvent
});
}
sendLeaveEvent(name: string) {
this.postMessage({
'type': 'leaveEvent',
'data': {
"name": name
} as EnterLeaveEvent
});
}
sendButtonClickedEvent(popupId: number, buttonId: number): void {
this.postMessage({
'type': 'buttonClickedEvent',
'data': {
popupId,
buttonId
} as ButtonClickedEvent
});
}
/**
* Sends the message... to all allowed iframes.
*/
private postMessage(message: IframeResponseEvent<keyof IframeResponseEventMap>) {
for (const iframe of this.iframes) {
iframe.contentWindow?.postMessage(message, '*');
}
}
}
export const iframeListener = new IframeListener();

View File

@ -0,0 +1,23 @@
import {coWebsiteManager} from "../WebRtc/CoWebsiteManager";
class ScriptUtils {
public openTab(url : string){
window.open(url);
}
public goToPage(url : string){
window.location.href = url;
}
public openCoWebsite(url: string, base: string) {
coWebsiteManager.loadCoWebsite(url, base);
}
public closeCoWebSite(){
coWebsiteManager.closeCoWebsite();
}
}
export const scriptUtils = new ScriptUtils();

View File

@ -0,0 +1,11 @@
<script lang="typescript">
import MenuIcon from "./Menu/MenuIcon.svelte";
import {menuIconVisible} from "../Stores/MenuStore";
</script>
<div>
<!-- {#if $menuIconVisible}
<MenuIcon />
{/if} -->
</div>

Some files were not shown because too many files have changed in this diff Show More