Merge branch 'develop' of github.com:thecodingmachine/workadventure into jonnytest1-tiles-start-positions
2
.github/workflows/build-and-deploy.yml
vendored
@ -199,4 +199,4 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
msg: Environment deployed at https://play-${{ env.GITHUB_HEAD_REF_SLUG }}.test.workadventu.re
|
msg: "Environment deployed at https://play-${{ env.GITHUB_HEAD_REF_SLUG }}.test.workadventu.re \nTests available at https://maps-${{ env.GITHUB_HEAD_REF_SLUG }}.test.workadventu.re/tests"
|
||||||
|
13
.github/workflows/push-to-npm.yml
vendored
@ -2,6 +2,7 @@ name: Push @workadventure/iframe-api-typings to NPM
|
|||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [created]
|
types: [created]
|
||||||
|
push:
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -13,10 +14,6 @@ jobs:
|
|||||||
node-version: '14.x'
|
node-version: '14.x'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
|
||||||
- name: Edit tsconfig.json to add declarations
|
|
||||||
run: "sed -i 's/\"declaration\": false/\"declaration\": true/g' tsconfig.json"
|
|
||||||
working-directory: "front"
|
|
||||||
|
|
||||||
- name: Replace version number
|
- name: Replace version number
|
||||||
run: 'sed -i "s#VERSION_PLACEHOLDER#${GITHUB_REF/refs\/tags\//}#g" package.json'
|
run: 'sed -i "s#VERSION_PLACEHOLDER#${GITHUB_REF/refs\/tags\//}#g" package.json'
|
||||||
working-directory: "front/packages/iframe-api-typings"
|
working-directory: "front/packages/iframe-api-typings"
|
||||||
@ -47,15 +44,18 @@ jobs:
|
|||||||
working-directory: "front"
|
working-directory: "front"
|
||||||
|
|
||||||
- name: "Build"
|
- name: "Build"
|
||||||
run: yarn run build
|
run: yarn run build-typings
|
||||||
env:
|
env:
|
||||||
API_URL: "localhost:8080"
|
PUSHER_URL: "//localhost:8080"
|
||||||
working-directory: "front"
|
working-directory: "front"
|
||||||
|
|
||||||
# We build the front to generate the typings of iframe_api, then we copy those typings in a separate package.
|
# We build the front to generate the typings of iframe_api, then we copy those typings in a separate package.
|
||||||
- name: Copy typings to package dir
|
- name: Copy typings to package dir
|
||||||
run: cp front/dist/src/iframe_api.d.ts front/packages/iframe-api-typings/iframe_api.d.ts
|
run: cp front/dist/src/iframe_api.d.ts front/packages/iframe-api-typings/iframe_api.d.ts
|
||||||
|
|
||||||
|
- name: Copy typings to package dir (2)
|
||||||
|
run: cp -R front/dist/src/Api front/packages/iframe-api-typings/Api
|
||||||
|
|
||||||
- name: Install dependencies in package
|
- name: Install dependencies in package
|
||||||
run: yarn install
|
run: yarn install
|
||||||
working-directory: "front/packages/iframe-api-typings"
|
working-directory: "front/packages/iframe-api-typings"
|
||||||
@ -65,3 +65,4 @@ jobs:
|
|||||||
working-directory: "front/packages/iframe-api-typings"
|
working-directory: "front/packages/iframe-api-typings"
|
||||||
env:
|
env:
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
if: ${{ github.event_name == 'release' }}
|
||||||
|
13
CHANGELOG.md
@ -15,6 +15,19 @@
|
|||||||
- Use `WA.room.getCurrentUser(): Promise<User>` to get the ID, name and tags of the current player
|
- Use `WA.room.getCurrentUser(): Promise<User>` to get the ID, name and tags of the current player
|
||||||
- Use `WA.room.getCurrentRoom(): Promise<Room>` to get the ID, JSON map file, url of the map of the current room and the layer where the current player started
|
- Use `WA.room.getCurrentRoom(): Promise<Room>` to get the ID, JSON map file, url of the map of the current room and the layer where the current player started
|
||||||
- Use `WA.ui.registerMenuCommand(): void` to add a custom menu
|
- Use `WA.ui.registerMenuCommand(): void` to add a custom menu
|
||||||
|
- Use `WA.room.setTiles(): void` to change an array of tiles
|
||||||
|
|
||||||
|
## Version 1.4.3 - 1.4.4 - 1.4.5
|
||||||
|
|
||||||
|
## Bugfixes
|
||||||
|
|
||||||
|
- Fixing the generation of @workadventure/iframe-api-typings
|
||||||
|
|
||||||
|
## Version 1.4.2
|
||||||
|
|
||||||
|
## Updates
|
||||||
|
|
||||||
|
- A script in an iframe opened by another script can use the IFrame API.
|
||||||
|
|
||||||
## Version 1.4.1
|
## Version 1.4.1
|
||||||
|
|
||||||
|
@ -52,11 +52,11 @@ WA.nav.goToRoom("/_/global/<path to global map>.json#start-layer-2")
|
|||||||
### Opening/closing a web page in an iFrame
|
### Opening/closing a web page in an iFrame
|
||||||
|
|
||||||
```
|
```
|
||||||
WA.nav.openCoWebSite(url: string): void
|
WA.nav.openCoWebSite(url: string, allowApi: boolean = false, allowPolicy: string = ""): void
|
||||||
WA.nav.closeCoWebSite(): void
|
WA.nav.closeCoWebSite(): void
|
||||||
```
|
```
|
||||||
|
|
||||||
Opens the webpage at "url" in an iFrame (on the right side of the screen) or close that iFrame.
|
Opens the webpage at "url" in an iFrame (on the right side of the screen) or close that iFrame. `allowApi` allows the webpage to use the "IFrame API" and execute script (it is equivalent to putting the `openWebsiteAllowApi` property in the map). `allowPolicy` grants additional access rights to the iFrame. The `allowPolicy` parameter is turned into an [`allow` feature policy in the iFrame](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-allow).
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -65,4 +65,3 @@ WA.nav.openCoWebSite('https://www.wikipedia.org/');
|
|||||||
// ...
|
// ...
|
||||||
WA.nav.closeCoWebSite();
|
WA.nav.closeCoWebSite();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -9,4 +9,4 @@
|
|||||||
- [Sound functions](api-sound.md)
|
- [Sound functions](api-sound.md)
|
||||||
- [Controls functions](api-controls.md)
|
- [Controls functions](api-controls.md)
|
||||||
|
|
||||||
- [List of deprecated functions](api-deprecated.md)
|
- [List of deprecated functions](api-deprecated.md)
|
||||||
|
@ -112,3 +112,35 @@ WA.room.getCurrentUser().then((user) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Changing tiles
|
||||||
|
```
|
||||||
|
WA.room.setTiles(tiles: TileDescriptor[]): void
|
||||||
|
```
|
||||||
|
Replace the tile at the `x` and `y` coordinates in the layer named `layer` by the tile with the id `tile`.
|
||||||
|
|
||||||
|
If `tile` is a string, it's not the id of the tile but the value of the property `name`.
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<img src="https://workadventu.re/img/docs/nameIndexProperty.png" class="figure-img img-fluid rounded" alt="" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
`TileDescriptor` has the following attributes :
|
||||||
|
* **x (number) :** The coordinate x of the tile that you want to replace.
|
||||||
|
* **y (number) :** The coordinate y of the tile that you want to replace.
|
||||||
|
* **tile (number | string) :** The id of the tile that will be placed in the map.
|
||||||
|
* **layer (string) :** The name of the layer where the tile will be placed.
|
||||||
|
|
||||||
|
**Important !** : If you use `tile` as a number, be sure to add the `firstgid` of the tileset of the tile that you want to the id of the tile in Tiled Editor.
|
||||||
|
|
||||||
|
|
||||||
|
Example :
|
||||||
|
```javascript
|
||||||
|
WA.room.setTiles([
|
||||||
|
{x: 6, y: 4, tile: 'blue', layer: 'setTiles'},
|
||||||
|
{x: 7, y: 4, tile: 109, layer: 'setTiles'},
|
||||||
|
{x: 8, y: 4, tile: 109, layer: 'setTiles'},
|
||||||
|
{x: 9, y: 4, tile: 'blue', layer: 'setTiles'}
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 880 B |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 933 B |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 978 B |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 985 B |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.2 KiB |
BIN
front/dist/static/images/favicons/apple-icon.png
vendored
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.2 KiB |
BIN
front/dist/static/images/favicons/favicon-16x16.png
vendored
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 713 B |
BIN
front/dist/static/images/favicons/favicon-32x32.png
vendored
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 848 B |
BIN
front/dist/static/images/favicons/favicon-96x96.png
vendored
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
front/dist/static/images/favicons/favicon.ico
vendored
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 3.5 KiB |
BIN
front/dist/static/images/favicons/ms-icon-70x70.png
vendored
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.1 KiB |
@ -60,6 +60,7 @@
|
|||||||
"templater": "cross-env ./templater.sh",
|
"templater": "cross-env ./templater.sh",
|
||||||
"serve": "cross-env TS_NODE_PROJECT=\"tsconfig-for-webpack.json\" webpack serve --open",
|
"serve": "cross-env TS_NODE_PROJECT=\"tsconfig-for-webpack.json\" webpack serve --open",
|
||||||
"build": "cross-env TS_NODE_PROJECT=\"tsconfig-for-webpack.json\" NODE_ENV=production webpack",
|
"build": "cross-env TS_NODE_PROJECT=\"tsconfig-for-webpack.json\" NODE_ENV=production webpack",
|
||||||
|
"build-typings": "cross-env TS_NODE_PROJECT=\"tsconfig-for-webpack.json\" NODE_ENV=production BUILD_TYPINGS=1 webpack",
|
||||||
"test": "cross-env TS_NODE_PROJECT=\"tsconfig-for-jasmine.json\" ts-node node_modules/jasmine/bin/jasmine --config=jasmine.json",
|
"test": "cross-env 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",
|
"lint": "node_modules/.bin/eslint src/ . --ext .ts",
|
||||||
"fix": "node_modules/.bin/eslint --fix src/ . --ext .ts",
|
"fix": "node_modules/.bin/eslint --fix src/ . --ext .ts",
|
||||||
|
@ -17,14 +17,13 @@ import type { PlaySoundEvent } from "./PlaySoundEvent";
|
|||||||
import type { MenuItemClickedEvent } from "./ui/MenuItemClickedEvent";
|
import type { MenuItemClickedEvent } from "./ui/MenuItemClickedEvent";
|
||||||
import type { MenuItemRegisterEvent } from "./ui/MenuItemRegisterEvent";
|
import type { MenuItemRegisterEvent } from "./ui/MenuItemRegisterEvent";
|
||||||
import type { HasPlayerMovedEvent } from "./HasPlayerMovedEvent";
|
import type { HasPlayerMovedEvent } from "./HasPlayerMovedEvent";
|
||||||
|
import type { SetTilesEvent } from "./SetTilesEvent";
|
||||||
|
|
||||||
export interface TypedMessageEvent<T> extends MessageEvent {
|
export interface TypedMessageEvent<T> extends MessageEvent {
|
||||||
data: T;
|
data: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IframeEventMap = {
|
export type IframeEventMap = {
|
||||||
//getState: GameStateEvent,
|
|
||||||
// updateTile: UpdateTileEvent
|
|
||||||
loadPage: LoadPageEvent;
|
loadPage: LoadPageEvent;
|
||||||
chat: ChatEvent;
|
chat: ChatEvent;
|
||||||
openPopup: OpenPopupEvent;
|
openPopup: OpenPopupEvent;
|
||||||
@ -47,6 +46,7 @@ export type IframeEventMap = {
|
|||||||
stopSound: null;
|
stopSound: null;
|
||||||
getState: undefined;
|
getState: undefined;
|
||||||
registerMenuCommand: MenuItemRegisterEvent;
|
registerMenuCommand: MenuItemRegisterEvent;
|
||||||
|
setTiles: SetTilesEvent;
|
||||||
};
|
};
|
||||||
export interface IframeEvent<T extends keyof IframeEventMap> {
|
export interface IframeEvent<T extends keyof IframeEventMap> {
|
||||||
type: T;
|
type: T;
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import * as tg from "generic-type-guard";
|
import * as tg from "generic-type-guard";
|
||||||
|
|
||||||
|
export const isOpenCoWebsite = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
export const isOpenCoWebsite =
|
|
||||||
new tg.IsInterface().withProperties({
|
|
||||||
url: tg.isString,
|
url: tg.isString,
|
||||||
}).get();
|
allowApi: tg.isBoolean,
|
||||||
|
allowPolicy: tg.isString,
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A message sent from the iFrame to the game to add a message in the chat.
|
* A message sent from the iFrame to the game to add a message in the chat.
|
||||||
|
16
front/src/Api/Events/SetTilesEvent.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import * as tg from "generic-type-guard";
|
||||||
|
|
||||||
|
export const isSetTilesEvent = tg.isArray(
|
||||||
|
new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
x: tg.isNumber,
|
||||||
|
y: tg.isNumber,
|
||||||
|
tile: tg.isUnion(tg.isNumber, tg.isString),
|
||||||
|
layer: tg.isString,
|
||||||
|
})
|
||||||
|
.get()
|
||||||
|
);
|
||||||
|
/**
|
||||||
|
* A message sent from the iFrame to the game to set one or many tiles.
|
||||||
|
*/
|
||||||
|
export type SetTilesEvent = tg.GuardedType<typeof isSetTilesEvent>;
|
@ -18,7 +18,6 @@ import {
|
|||||||
TypedMessageEvent,
|
TypedMessageEvent,
|
||||||
} from "./Events/IframeEvent";
|
} from "./Events/IframeEvent";
|
||||||
import type { UserInputChatEvent } from "./Events/UserInputChatEvent";
|
import type { UserInputChatEvent } from "./Events/UserInputChatEvent";
|
||||||
//import { isLoadPageEvent } from './Events/LoadPageEvent';
|
|
||||||
import { isPlaySoundEvent, PlaySoundEvent } from "./Events/PlaySoundEvent";
|
import { isPlaySoundEvent, PlaySoundEvent } from "./Events/PlaySoundEvent";
|
||||||
import { isStopSoundEvent, StopSoundEvent } from "./Events/StopSoundEvent";
|
import { isStopSoundEvent, StopSoundEvent } from "./Events/StopSoundEvent";
|
||||||
import { isLoadSoundEvent, LoadSoundEvent } from "./Events/LoadSoundEvent";
|
import { isLoadSoundEvent, LoadSoundEvent } from "./Events/LoadSoundEvent";
|
||||||
@ -30,6 +29,7 @@ import type { GameStateEvent } from "./Events/GameStateEvent";
|
|||||||
import type { HasPlayerMovedEvent } from "./Events/HasPlayerMovedEvent";
|
import type { HasPlayerMovedEvent } from "./Events/HasPlayerMovedEvent";
|
||||||
import { isLoadPageEvent } from "./Events/LoadPageEvent";
|
import { isLoadPageEvent } from "./Events/LoadPageEvent";
|
||||||
import { handleMenuItemRegistrationEvent, isMenuItemRegisterIframeEvent } from "./Events/ui/MenuItemRegisterEvent";
|
import { handleMenuItemRegistrationEvent, isMenuItemRegisterIframeEvent } from "./Events/ui/MenuItemRegisterEvent";
|
||||||
|
import { SetTilesEvent, isSetTilesEvent } from "./Events/SetTilesEvent";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listens to messages from iframes and turn those messages into easy to use observables.
|
* Listens to messages from iframes and turn those messages into easy to use observables.
|
||||||
@ -102,6 +102,9 @@ class IframeListener {
|
|||||||
private readonly _loadSoundStream: Subject<LoadSoundEvent> = new Subject();
|
private readonly _loadSoundStream: Subject<LoadSoundEvent> = new Subject();
|
||||||
public readonly loadSoundStream = this._loadSoundStream.asObservable();
|
public readonly loadSoundStream = this._loadSoundStream.asObservable();
|
||||||
|
|
||||||
|
private readonly _setTilesStream: Subject<SetTilesEvent> = new Subject();
|
||||||
|
public readonly setTilesStream = this._setTilesStream.asObservable();
|
||||||
|
|
||||||
private readonly iframes = new Set<HTMLIFrameElement>();
|
private readonly iframes = new Set<HTMLIFrameElement>();
|
||||||
private readonly iframeCloseCallbacks = new Map<HTMLIFrameElement, (() => void)[]>();
|
private readonly iframeCloseCallbacks = new Map<HTMLIFrameElement, (() => void)[]>();
|
||||||
private readonly scripts = new Map<string, HTMLIFrameElement>();
|
private readonly scripts = new Map<string, HTMLIFrameElement>();
|
||||||
@ -124,11 +127,22 @@ class IframeListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const payload = message.data;
|
||||||
|
|
||||||
if (foundSrc === undefined) {
|
if (foundSrc === undefined) {
|
||||||
|
if (isIframeEventWrapper(payload)) {
|
||||||
|
console.warn(
|
||||||
|
"It seems an iFrame is trying to communicate with WorkAdventure but was not explicitly granted the permission to do so. " +
|
||||||
|
"If you are looking to use the WorkAdventure Scripting API inside an iFrame, you should allow the " +
|
||||||
|
'iFrame to communicate with WorkAdventure by using the "openWebsiteAllowApi" property in your map (or passing "true" as a second' +
|
||||||
|
"parameter to WA.nav.openCoWebSite())"
|
||||||
|
);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const payload = message.data;
|
foundSrc = this.getBaseUrl(foundSrc, message.source);
|
||||||
|
|
||||||
if (isIframeEventWrapper(payload)) {
|
if (isIframeEventWrapper(payload)) {
|
||||||
if (payload.type === "showLayer" && isLayerEvent(payload.data)) {
|
if (payload.type === "showLayer" && isLayerEvent(payload.data)) {
|
||||||
this._showLayerStream.next(payload.data);
|
this._showLayerStream.next(payload.data);
|
||||||
@ -155,7 +169,12 @@ class IframeListener {
|
|||||||
} else if (payload.type === "loadSound" && isLoadSoundEvent(payload.data)) {
|
} else if (payload.type === "loadSound" && isLoadSoundEvent(payload.data)) {
|
||||||
this._loadSoundStream.next(payload.data);
|
this._loadSoundStream.next(payload.data);
|
||||||
} else if (payload.type === "openCoWebSite" && isOpenCoWebsite(payload.data)) {
|
} else if (payload.type === "openCoWebSite" && isOpenCoWebsite(payload.data)) {
|
||||||
scriptUtils.openCoWebsite(payload.data.url, foundSrc);
|
scriptUtils.openCoWebsite(
|
||||||
|
payload.data.url,
|
||||||
|
foundSrc,
|
||||||
|
payload.data.allowApi,
|
||||||
|
payload.data.allowPolicy
|
||||||
|
);
|
||||||
} else if (payload.type === "closeCoWebSite") {
|
} else if (payload.type === "closeCoWebSite") {
|
||||||
scriptUtils.closeCoWebSite();
|
scriptUtils.closeCoWebSite();
|
||||||
} else if (payload.type === "disablePlayerControls") {
|
} else if (payload.type === "disablePlayerControls") {
|
||||||
@ -179,6 +198,8 @@ class IframeListener {
|
|||||||
this._unregisterMenuCommandStream.next(data);
|
this._unregisterMenuCommandStream.next(data);
|
||||||
});
|
});
|
||||||
handleMenuItemRegistrationEvent(payload.data);
|
handleMenuItemRegistrationEvent(payload.data);
|
||||||
|
} else if (payload.type == "setTiles" && isSetTilesEvent(payload.data)) {
|
||||||
|
this._setTilesStream.next(payload.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -268,6 +289,15 @@ class IframeListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getBaseUrl(src: string, source: MessageEventSource | null): string {
|
||||||
|
for (const script of this.scripts) {
|
||||||
|
if (script[1].contentWindow === source) {
|
||||||
|
return script[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
|
||||||
private static getIFrameId(scriptUrl: string): string {
|
private static getIFrameId(scriptUrl: string): string {
|
||||||
return "script" + btoa(scriptUrl);
|
return "script" + btoa(scriptUrl);
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
import {coWebsiteManager} from "../WebRtc/CoWebsiteManager";
|
import { coWebsiteManager } from "../WebRtc/CoWebsiteManager";
|
||||||
|
|
||||||
class ScriptUtils {
|
class ScriptUtils {
|
||||||
|
public openTab(url: string) {
|
||||||
public openTab(url : string){
|
|
||||||
window.open(url);
|
window.open(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public goToPage(url : string){
|
public goToPage(url: string) {
|
||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public openCoWebsite(url: string, base: string) {
|
public openCoWebsite(url: string, base: string, api: boolean, policy: string) {
|
||||||
coWebsiteManager.loadCoWebsite(url, base);
|
coWebsiteManager.loadCoWebsite(url, base, api, policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeCoWebSite(){
|
public closeCoWebSite() {
|
||||||
coWebsiteManager.closeCoWebsite();
|
coWebsiteManager.closeCoWebsite();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import { Subject } from "rxjs";
|
|||||||
|
|
||||||
const chatStream = new Subject<string>();
|
const chatStream = new Subject<string>();
|
||||||
|
|
||||||
class WorkadventureChatCommands extends IframeApiContribution<WorkadventureChatCommands> {
|
export class WorkadventureChatCommands extends IframeApiContribution<WorkadventureChatCommands> {
|
||||||
callbacks = [
|
callbacks = [
|
||||||
apiCallback({
|
apiCallback({
|
||||||
callback: (event: UserInputChatEvent) => {
|
callback: (event: UserInputChatEvent) => {
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
import { IframeApiContribution, sendToWorkadventure } from './IframeApiContribution';
|
import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribution";
|
||||||
|
|
||||||
class WorkadventureControlsCommands extends IframeApiContribution<WorkadventureControlsCommands> {
|
export class WorkadventureControlsCommands extends IframeApiContribution<WorkadventureControlsCommands> {
|
||||||
callbacks = []
|
callbacks = [];
|
||||||
|
|
||||||
disablePlayerControls(): void {
|
disablePlayerControls(): void {
|
||||||
sendToWorkadventure({ 'type': 'disablePlayerControls', data: null });
|
sendToWorkadventure({ type: "disablePlayerControls", data: null });
|
||||||
}
|
}
|
||||||
|
|
||||||
restorePlayerControls(): void {
|
restorePlayerControls(): void {
|
||||||
sendToWorkadventure({ 'type': 'restorePlayerControls', data: null });
|
sendToWorkadventure({ type: "restorePlayerControls", data: null });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default new WorkadventureControlsCommands();
|
export default new WorkadventureControlsCommands();
|
||||||
|
@ -4,7 +4,7 @@ import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribut
|
|||||||
import type { OpenCoWebSiteEvent } from "../Events/OpenCoWebSiteEvent";
|
import type { OpenCoWebSiteEvent } from "../Events/OpenCoWebSiteEvent";
|
||||||
import type { LoadPageEvent } from "../Events/LoadPageEvent";
|
import type { LoadPageEvent } from "../Events/LoadPageEvent";
|
||||||
|
|
||||||
class WorkadventureNavigationCommands extends IframeApiContribution<WorkadventureNavigationCommands> {
|
export class WorkadventureNavigationCommands extends IframeApiContribution<WorkadventureNavigationCommands> {
|
||||||
callbacks = [];
|
callbacks = [];
|
||||||
|
|
||||||
openTab(url: string): void {
|
openTab(url: string): void {
|
||||||
@ -34,11 +34,13 @@ class WorkadventureNavigationCommands extends IframeApiContribution<Workadventur
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
openCoWebSite(url: string): void {
|
openCoWebSite(url: string, allowApi: boolean = false, allowPolicy: string = ""): void {
|
||||||
sendToWorkadventure({
|
sendToWorkadventure({
|
||||||
type: "openCoWebSite",
|
type: "openCoWebSite",
|
||||||
data: {
|
data: {
|
||||||
url,
|
url,
|
||||||
|
allowApi,
|
||||||
|
allowPolicy,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import { isHasPlayerMovedEvent } from "../Events/HasPlayerMovedEvent";
|
|||||||
|
|
||||||
const moveStream = new Subject<HasPlayerMovedEvent>();
|
const moveStream = new Subject<HasPlayerMovedEvent>();
|
||||||
|
|
||||||
class WorkadventurePlayerCommands extends IframeApiContribution<WorkadventurePlayerCommands> {
|
export class WorkadventurePlayerCommands extends IframeApiContribution<WorkadventurePlayerCommands> {
|
||||||
callbacks = [
|
callbacks = [
|
||||||
apiCallback({
|
apiCallback({
|
||||||
type: "hasPlayerMoved",
|
type: "hasPlayerMoved",
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import { Subject } from "rxjs";
|
import { Subject } from "rxjs";
|
||||||
|
|
||||||
|
import { isDataLayerEvent } from "../Events/DataLayerEvent";
|
||||||
import { EnterLeaveEvent, isEnterLeaveEvent } from "../Events/EnterLeaveEvent";
|
import { EnterLeaveEvent, isEnterLeaveEvent } from "../Events/EnterLeaveEvent";
|
||||||
|
import { isGameStateEvent } from "../Events/GameStateEvent";
|
||||||
|
|
||||||
import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribution";
|
import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribution";
|
||||||
import { apiCallback } from "./registeredCallbacks";
|
import { apiCallback } from "./registeredCallbacks";
|
||||||
import type { LayerEvent } from "../Events/LayerEvent";
|
|
||||||
import type { SetPropertyEvent } from "../Events/setPropertyEvent";
|
|
||||||
import type { GameStateEvent } from "../Events/GameStateEvent";
|
|
||||||
import type { ITiledMap } from "../../Phaser/Map/ITiledMap";
|
import type { ITiledMap } from "../../Phaser/Map/ITiledMap";
|
||||||
import type { DataLayerEvent } from "../Events/DataLayerEvent";
|
import type { DataLayerEvent } from "../Events/DataLayerEvent";
|
||||||
import { isGameStateEvent } from "../Events/GameStateEvent";
|
import type { GameStateEvent } from "../Events/GameStateEvent";
|
||||||
import { isDataLayerEvent } from "../Events/DataLayerEvent";
|
|
||||||
|
|
||||||
const enterStreams: Map<string, Subject<EnterLeaveEvent>> = new Map<string, Subject<EnterLeaveEvent>>();
|
const enterStreams: Map<string, Subject<EnterLeaveEvent>> = new Map<string, Subject<EnterLeaveEvent>>();
|
||||||
const leaveStreams: Map<string, Subject<EnterLeaveEvent>> = new Map<string, Subject<EnterLeaveEvent>>();
|
const leaveStreams: Map<string, Subject<EnterLeaveEvent>> = new Map<string, Subject<EnterLeaveEvent>>();
|
||||||
@ -30,6 +31,13 @@ interface User {
|
|||||||
tags: string[];
|
tags: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface TileDescriptor {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
tile: number | string;
|
||||||
|
layer: string;
|
||||||
|
}
|
||||||
|
|
||||||
function getGameState(): Promise<GameStateEvent> {
|
function getGameState(): Promise<GameStateEvent> {
|
||||||
if (immutableData) {
|
if (immutableData) {
|
||||||
return Promise.resolve(immutableData);
|
return Promise.resolve(immutableData);
|
||||||
@ -48,7 +56,7 @@ function getDataLayer(): Promise<DataLayerEvent> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class WorkadventureRoomCommands extends IframeApiContribution<WorkadventureRoomCommands> {
|
export class WorkadventureRoomCommands extends IframeApiContribution<WorkadventureRoomCommands> {
|
||||||
callbacks = [
|
callbacks = [
|
||||||
apiCallback({
|
apiCallback({
|
||||||
callback: (payloadData: EnterLeaveEvent) => {
|
callback: (payloadData: EnterLeaveEvent) => {
|
||||||
@ -129,6 +137,12 @@ class WorkadventureRoomCommands extends IframeApiContribution<WorkadventureRoomC
|
|||||||
return { id: gameState.uuid, nickName: gameState.nickname, tags: gameState.tags };
|
return { id: gameState.uuid, nickName: gameState.nickname, tags: gameState.tags };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
setTiles(tiles: TileDescriptor[]) {
|
||||||
|
sendToWorkadventure({
|
||||||
|
type: "setTiles",
|
||||||
|
data: tiles,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new WorkadventureRoomCommands();
|
export default new WorkadventureRoomCommands();
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
import type { LoadSoundEvent } from '../Events/LoadSoundEvent';
|
import type { LoadSoundEvent } from "../Events/LoadSoundEvent";
|
||||||
import type { PlaySoundEvent } from '../Events/PlaySoundEvent';
|
import type { PlaySoundEvent } from "../Events/PlaySoundEvent";
|
||||||
import type { StopSoundEvent } from '../Events/StopSoundEvent';
|
import type { StopSoundEvent } from "../Events/StopSoundEvent";
|
||||||
import { IframeApiContribution, sendToWorkadventure } from './IframeApiContribution';
|
import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribution";
|
||||||
import {Sound} from "./Sound/Sound";
|
import { Sound } from "./Sound/Sound";
|
||||||
|
|
||||||
class WorkadventureSoundCommands extends IframeApiContribution<WorkadventureSoundCommands> {
|
export class WorkadventureSoundCommands extends IframeApiContribution<WorkadventureSoundCommands> {
|
||||||
callbacks = []
|
callbacks = [];
|
||||||
|
|
||||||
loadSound(url: string): Sound {
|
loadSound(url: string): Sound {
|
||||||
return new Sound(url);
|
return new Sound(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default new WorkadventureSoundCommands();
|
export default new WorkadventureSoundCommands();
|
||||||
|
@ -23,7 +23,7 @@ interface ZonedPopupOptions {
|
|||||||
popupOptions: Array<ButtonDescriptor>;
|
popupOptions: Array<ButtonDescriptor>;
|
||||||
}
|
}
|
||||||
|
|
||||||
class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventureUiCommands> {
|
export class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventureUiCommands> {
|
||||||
callbacks = [
|
callbacks = [
|
||||||
apiCallback({
|
apiCallback({
|
||||||
type: "buttonClickedEvent",
|
type: "buttonClickedEvent",
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import type { Game } from "../../Phaser/Game/Game";
|
import type { Game } from "../../Phaser/Game/Game";
|
||||||
import {CustomizeScene, CustomizeSceneName} from "../../Phaser/Login/CustomizeScene";
|
import {CustomizeScene, CustomizeSceneName} from "../../Phaser/Login/CustomizeScene";
|
||||||
|
import {activeRowStore} from "../../Stores/CustomCharacterStore";
|
||||||
|
|
||||||
export let game: Game;
|
export let game: Game;
|
||||||
|
|
||||||
const customCharacterScene = game.scene.getScene(CustomizeSceneName) as CustomizeScene;
|
const customCharacterScene = game.scene.getScene(CustomizeSceneName) as CustomizeScene;
|
||||||
let activeRow = customCharacterScene.activeRow;
|
|
||||||
|
|
||||||
function selectLeft() {
|
function selectLeft() {
|
||||||
customCharacterScene.moveCursorHorizontally(-1);
|
customCharacterScene.moveCursorHorizontally(-1);
|
||||||
@ -17,12 +17,10 @@
|
|||||||
|
|
||||||
function selectUp() {
|
function selectUp() {
|
||||||
customCharacterScene.moveCursorVertically(-1);
|
customCharacterScene.moveCursorVertically(-1);
|
||||||
activeRow = customCharacterScene.activeRow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectDown() {
|
function selectDown() {
|
||||||
customCharacterScene.moveCursorVertically(1);
|
customCharacterScene.moveCursorVertically(1);
|
||||||
activeRow = customCharacterScene.activeRow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function previousScene() {
|
function previousScene() {
|
||||||
@ -44,16 +42,16 @@
|
|||||||
<button class="customCharacterSceneButton customCharacterSceneButtonRight nes-btn" on:click|preventDefault={ selectRight }> > </button>
|
<button class="customCharacterSceneButton customCharacterSceneButtonRight nes-btn" on:click|preventDefault={ selectRight }> > </button>
|
||||||
</section>
|
</section>
|
||||||
<section class="action">
|
<section class="action">
|
||||||
{#if activeRow === 0}
|
{#if $activeRowStore === 0}
|
||||||
<button type="submit" class="customCharacterSceneFormBack nes-btn" on:click|preventDefault={ previousScene }>Return</button>
|
<button type="submit" class="customCharacterSceneFormBack nes-btn" on:click|preventDefault={ previousScene }>Return</button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if activeRow !== 0}
|
{#if $activeRowStore !== 0}
|
||||||
<button type="submit" class="customCharacterSceneFormBack nes-btn" on:click|preventDefault={ selectUp }>Back <img src="resources/objects/arrow_up_black.png" alt=""/></button>
|
<button type="submit" class="customCharacterSceneFormBack nes-btn" on:click|preventDefault={ selectUp }>Back <img src="resources/objects/arrow_up_black.png" alt=""/></button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if activeRow === 5}
|
{#if $activeRowStore === 5}
|
||||||
<button type="submit" class="customCharacterSceneFormSubmit nes-btn is-primary" on:click|preventDefault={ finish }>Finish</button>
|
<button type="submit" class="customCharacterSceneFormSubmit nes-btn is-primary" on:click|preventDefault={ finish }>Finish</button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if activeRow !== 5}
|
{#if $activeRowStore !== 5}
|
||||||
<button type="submit" class="customCharacterSceneFormSubmit nes-btn is-primary" on:click|preventDefault={ selectDown }>Next <img src="resources/objects/arrow_down.png" alt=""/></button>
|
<button type="submit" class="customCharacterSceneFormSubmit nes-btn is-primary" on:click|preventDefault={ selectDown }>Next <img src="resources/objects/arrow_down.png" alt=""/></button>
|
||||||
{/if}
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
|
@ -1,90 +1,124 @@
|
|||||||
import LoaderPlugin = Phaser.Loader.LoaderPlugin;
|
import LoaderPlugin = Phaser.Loader.LoaderPlugin;
|
||||||
import type {CharacterTexture} from "../../Connexion/LocalUser";
|
import type { CharacterTexture } from "../../Connexion/LocalUser";
|
||||||
import {BodyResourceDescriptionInterface, LAYERS, PLAYER_RESOURCES} from "./PlayerTextures";
|
import { BodyResourceDescriptionInterface, LAYERS, PLAYER_RESOURCES } from "./PlayerTextures";
|
||||||
|
|
||||||
export interface FrameConfig {
|
export interface FrameConfig {
|
||||||
frameWidth: number,
|
frameWidth: number;
|
||||||
frameHeight: number,
|
frameHeight: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const loadAllLayers = (load: LoaderPlugin): BodyResourceDescriptionInterface[][] => {
|
export const loadAllLayers = (load: LoaderPlugin): BodyResourceDescriptionInterface[][] => {
|
||||||
const returnArray:BodyResourceDescriptionInterface[][] = [];
|
const returnArray: BodyResourceDescriptionInterface[][] = [];
|
||||||
LAYERS.forEach(layer => {
|
LAYERS.forEach((layer) => {
|
||||||
const layerArray:BodyResourceDescriptionInterface[] = [];
|
const layerArray: BodyResourceDescriptionInterface[] = [];
|
||||||
Object.values(layer).forEach((textureDescriptor) => {
|
Object.values(layer).forEach((textureDescriptor) => {
|
||||||
layerArray.push(textureDescriptor);
|
layerArray.push(textureDescriptor);
|
||||||
load.spritesheet(textureDescriptor.name,textureDescriptor.img,{frameWidth: 32, frameHeight: 32});
|
load.spritesheet(textureDescriptor.name, textureDescriptor.img, { frameWidth: 32, frameHeight: 32 });
|
||||||
})
|
});
|
||||||
returnArray.push(layerArray)
|
returnArray.push(layerArray);
|
||||||
});
|
});
|
||||||
return returnArray;
|
return returnArray;
|
||||||
}
|
};
|
||||||
export const loadAllDefaultModels = (load: LoaderPlugin): BodyResourceDescriptionInterface[] => {
|
export const loadAllDefaultModels = (load: LoaderPlugin): BodyResourceDescriptionInterface[] => {
|
||||||
const returnArray = Object.values(PLAYER_RESOURCES);
|
const returnArray = Object.values(PLAYER_RESOURCES);
|
||||||
returnArray.forEach((playerResource: BodyResourceDescriptionInterface) => {
|
returnArray.forEach((playerResource: BodyResourceDescriptionInterface) => {
|
||||||
load.spritesheet(playerResource.name, playerResource.img, {frameWidth: 32, frameHeight: 32});
|
load.spritesheet(playerResource.name, playerResource.img, { frameWidth: 32, frameHeight: 32 });
|
||||||
});
|
});
|
||||||
return returnArray;
|
return returnArray;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const loadCustomTexture = (loaderPlugin: LoaderPlugin, texture: CharacterTexture) : Promise<BodyResourceDescriptionInterface> => {
|
export const loadCustomTexture = (
|
||||||
const name = 'customCharacterTexture'+texture.id;
|
loaderPlugin: LoaderPlugin,
|
||||||
const playerResourceDescriptor: BodyResourceDescriptionInterface = {name, img: texture.url, level: texture.level}
|
texture: CharacterTexture
|
||||||
|
): Promise<BodyResourceDescriptionInterface> => {
|
||||||
|
const name = "customCharacterTexture" + texture.id;
|
||||||
|
const playerResourceDescriptor: BodyResourceDescriptionInterface = { name, img: texture.url, level: texture.level };
|
||||||
return createLoadingPromise(loaderPlugin, playerResourceDescriptor, {
|
return createLoadingPromise(loaderPlugin, playerResourceDescriptor, {
|
||||||
frameWidth: 32,
|
frameWidth: 32,
|
||||||
frameHeight: 32
|
frameHeight: 32,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export const lazyLoadPlayerCharacterTextures = (loadPlugin: LoaderPlugin, texturekeys:Array<string|BodyResourceDescriptionInterface>): Promise<string[]> => {
|
export const lazyLoadPlayerCharacterTextures = (
|
||||||
const promisesList:Promise<unknown>[] = [];
|
loadPlugin: LoaderPlugin,
|
||||||
texturekeys.forEach((textureKey: string|BodyResourceDescriptionInterface) => {
|
texturekeys: Array<string | BodyResourceDescriptionInterface>
|
||||||
|
): Promise<string[]> => {
|
||||||
|
const promisesList: Promise<unknown>[] = [];
|
||||||
|
texturekeys.forEach((textureKey: string | BodyResourceDescriptionInterface) => {
|
||||||
try {
|
try {
|
||||||
//TODO refactor
|
//TODO refactor
|
||||||
const playerResourceDescriptor = getRessourceDescriptor(textureKey);
|
const playerResourceDescriptor = getRessourceDescriptor(textureKey);
|
||||||
if (playerResourceDescriptor && !loadPlugin.textureManager.exists(playerResourceDescriptor.name)) {
|
if (playerResourceDescriptor && !loadPlugin.textureManager.exists(playerResourceDescriptor.name)) {
|
||||||
promisesList.push(createLoadingPromise(loadPlugin, playerResourceDescriptor, {
|
promisesList.push(
|
||||||
frameWidth: 32,
|
createLoadingPromise(loadPlugin, playerResourceDescriptor, {
|
||||||
frameHeight: 32
|
frameWidth: 32,
|
||||||
}));
|
frameHeight: 32,
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}catch (err){
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let returnPromise:Promise<Array<string|BodyResourceDescriptionInterface>>;
|
let returnPromise: Promise<Array<string | BodyResourceDescriptionInterface>>;
|
||||||
if (promisesList.length > 0) {
|
if (promisesList.length > 0) {
|
||||||
loadPlugin.start();
|
loadPlugin.start();
|
||||||
returnPromise = Promise.all(promisesList).then(() => texturekeys);
|
returnPromise = Promise.all(promisesList).then(() => texturekeys);
|
||||||
} else {
|
} else {
|
||||||
returnPromise = Promise.resolve(texturekeys);
|
returnPromise = Promise.resolve(texturekeys);
|
||||||
}
|
}
|
||||||
return returnPromise.then((keys) => keys.map((key) => {
|
|
||||||
return typeof key !== 'string' ? key.name : key;
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getRessourceDescriptor = (textureKey: string|BodyResourceDescriptionInterface): BodyResourceDescriptionInterface => {
|
//If the loading fail, we render the default model instead.
|
||||||
if (typeof textureKey !== 'string' && textureKey.img) {
|
return returnPromise
|
||||||
|
.then((keys) =>
|
||||||
|
keys.map((key) => {
|
||||||
|
return typeof key !== "string" ? key.name : key;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.catch(() => lazyLoadPlayerCharacterTextures(loadPlugin, ["color_22", "eyes_23"]));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getRessourceDescriptor = (
|
||||||
|
textureKey: string | BodyResourceDescriptionInterface
|
||||||
|
): BodyResourceDescriptionInterface => {
|
||||||
|
if (typeof textureKey !== "string" && textureKey.img) {
|
||||||
return textureKey;
|
return textureKey;
|
||||||
}
|
}
|
||||||
const textureName:string = typeof textureKey === 'string' ? textureKey : textureKey.name;
|
const textureName: string = typeof textureKey === "string" ? textureKey : textureKey.name;
|
||||||
const playerResource = PLAYER_RESOURCES[textureName];
|
const playerResource = PLAYER_RESOURCES[textureName];
|
||||||
if (playerResource !== undefined) return playerResource;
|
if (playerResource !== undefined) return playerResource;
|
||||||
|
|
||||||
for (let i=0; i<LAYERS.length;i++) {
|
for (let i = 0; i < LAYERS.length; i++) {
|
||||||
const playerResource = LAYERS[i][textureName];
|
const playerResource = LAYERS[i][textureName];
|
||||||
if (playerResource !== undefined) return playerResource;
|
if (playerResource !== undefined) return playerResource;
|
||||||
}
|
}
|
||||||
throw 'Could not find a data for texture '+textureName;
|
throw "Could not find a data for texture " + textureName;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const createLoadingPromise = (loadPlugin: LoaderPlugin, playerResourceDescriptor: BodyResourceDescriptionInterface, frameConfig: FrameConfig) => {
|
export const createLoadingPromise = (
|
||||||
return new Promise<BodyResourceDescriptionInterface>((res) => {
|
loadPlugin: LoaderPlugin,
|
||||||
|
playerResourceDescriptor: BodyResourceDescriptionInterface,
|
||||||
|
frameConfig: FrameConfig
|
||||||
|
) => {
|
||||||
|
return new Promise<BodyResourceDescriptionInterface>((res, rej) => {
|
||||||
|
console.log("count", loadPlugin.listenerCount("loaderror"));
|
||||||
if (loadPlugin.textureManager.exists(playerResourceDescriptor.name)) {
|
if (loadPlugin.textureManager.exists(playerResourceDescriptor.name)) {
|
||||||
return res(playerResourceDescriptor);
|
return res(playerResourceDescriptor);
|
||||||
}
|
}
|
||||||
loadPlugin.spritesheet(playerResourceDescriptor.name, playerResourceDescriptor.img, frameConfig);
|
loadPlugin.spritesheet(playerResourceDescriptor.name, playerResourceDescriptor.img, frameConfig);
|
||||||
loadPlugin.once('filecomplete-spritesheet-' + playerResourceDescriptor.name, () => res(playerResourceDescriptor));
|
const errorCallback = (file: { src: string }) => {
|
||||||
|
if (file.src !== playerResourceDescriptor.img) return;
|
||||||
|
console.error("failed loading player ressource: ", playerResourceDescriptor);
|
||||||
|
rej(playerResourceDescriptor);
|
||||||
|
loadPlugin.off("filecomplete-spritesheet-" + playerResourceDescriptor.name, successCallback);
|
||||||
|
loadPlugin.off("loaderror", errorCallback);
|
||||||
|
};
|
||||||
|
const successCallback = () => {
|
||||||
|
loadPlugin.off("loaderror", errorCallback);
|
||||||
|
res(playerResourceDescriptor);
|
||||||
|
};
|
||||||
|
|
||||||
|
loadPlugin.once("filecomplete-spritesheet-" + playerResourceDescriptor.name, successCallback);
|
||||||
|
loadPlugin.on("loaderror", errorCallback);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
@ -17,6 +17,7 @@ export class GameMap {
|
|||||||
private key: number | undefined;
|
private key: number | undefined;
|
||||||
private lastProperties = new Map<string, string | boolean | number>();
|
private lastProperties = new Map<string, string | boolean | number>();
|
||||||
private callbacks = new Map<string, Array<PropertyChangeCallback>>();
|
private callbacks = new Map<string, Array<PropertyChangeCallback>>();
|
||||||
|
private tileNameMap = new Map<string, number>();
|
||||||
|
|
||||||
private tileSetPropertyMap: { [tile_index: number]: Array<ITiledMapLayerProperty> } = {};
|
private tileSetPropertyMap: { [tile_index: number]: Array<ITiledMapLayerProperty> } = {};
|
||||||
public readonly flatLayers: ITiledMapLayer[];
|
public readonly flatLayers: ITiledMapLayer[];
|
||||||
@ -46,6 +47,9 @@ export class GameMap {
|
|||||||
if (tile.properties) {
|
if (tile.properties) {
|
||||||
this.tileSetPropertyMap[tileset.firstgid + tile.id] = tile.properties;
|
this.tileSetPropertyMap[tileset.firstgid + tile.id] = tile.properties;
|
||||||
tile.properties.forEach((prop) => {
|
tile.properties.forEach((prop) => {
|
||||||
|
if (prop.name == "name" && typeof prop.value == "string") {
|
||||||
|
this.tileNameMap.set(prop.value, tileset.firstgid + tile.id);
|
||||||
|
}
|
||||||
if (prop.name == "exitUrl" && typeof prop.value == "string") {
|
if (prop.name == "exitUrl" && typeof prop.value == "string") {
|
||||||
this.exitUrls.push(prop.value);
|
this.exitUrls.push(prop.value);
|
||||||
} else if (prop.name == "start") {
|
} else if (prop.name == "start") {
|
||||||
@ -147,6 +151,10 @@ export class GameMap {
|
|||||||
return this.map;
|
return this.map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getTileProperty(index: number): Array<ITiledMapLayerProperty> {
|
||||||
|
return this.tileSetPropertyMap[index];
|
||||||
|
}
|
||||||
|
|
||||||
private trigger(
|
private trigger(
|
||||||
propName: string,
|
propName: string,
|
||||||
oldValue: string | number | boolean | undefined,
|
oldValue: string | number | boolean | undefined,
|
||||||
@ -186,4 +194,48 @@ export class GameMap {
|
|||||||
phaserLayer.tileset.push(terrain);
|
phaserLayer.tileset.push(terrain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private putTileInFlatLayer(index: number, x: number, y: number, layer: string): void {
|
||||||
|
const fLayer = this.findLayer(layer);
|
||||||
|
if (fLayer == undefined) {
|
||||||
|
console.error("The layer that you want to change doesn't exist.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fLayer.type !== "tilelayer") {
|
||||||
|
console.error("The layer that you want to change is not a tilelayer. Tile can only be put in tilelayer.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof fLayer.data === "string") {
|
||||||
|
console.error("Data of the layer that you want to change is only readable.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fLayer.data[x + y * fLayer.height] = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public putTile(tile: string | number, x: number, y: number, layer: string): void {
|
||||||
|
const phaserLayer = this.findPhaserLayer(layer);
|
||||||
|
if (phaserLayer) {
|
||||||
|
const tileIndex = this.getIndexForTileType(tile);
|
||||||
|
if (tileIndex !== undefined) {
|
||||||
|
this.putTileInFlatLayer(tileIndex, x, y, layer);
|
||||||
|
const phaserTile = phaserLayer.putTileAt(tileIndex, x, y);
|
||||||
|
for (const property of this.getTileProperty(tileIndex)) {
|
||||||
|
if (property.name === "collides" && property.value === "true") {
|
||||||
|
phaserTile.setCollision(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error("The tile that you want to place doesn't exist.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error("The layer that you want to change is not a tilelayer. Tile can only be put in tilelayer.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getIndexForTileType(tile: string | number): number | undefined {
|
||||||
|
if (typeof tile == "number") {
|
||||||
|
return tile;
|
||||||
|
}
|
||||||
|
return this.tileNameMap.get(tile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
import type { Subscription } from "rxjs";
|
||||||
|
import { GlobalMessageManager } from "../../Administration/GlobalMessageManager";
|
||||||
|
import { userMessageManager } from "../../Administration/UserMessageManager";
|
||||||
|
import { iframeListener } from "../../Api/IframeListener";
|
||||||
|
import { connectionManager } from "../../Connexion/ConnectionManager";
|
||||||
import type {
|
import type {
|
||||||
GroupCreatedUpdatedMessageInterface,
|
GroupCreatedUpdatedMessageInterface,
|
||||||
MessageUserJoined,
|
MessageUserJoined,
|
||||||
@ -25,17 +30,13 @@ import {
|
|||||||
import { coWebsiteManager } from "../../WebRtc/CoWebsiteManager";
|
import { coWebsiteManager } from "../../WebRtc/CoWebsiteManager";
|
||||||
import type { UserMovedMessage } from "../../Messages/generated/messages_pb";
|
import type { UserMovedMessage } from "../../Messages/generated/messages_pb";
|
||||||
import { ProtobufClientUtils } from "../../Network/ProtobufClientUtils";
|
import { ProtobufClientUtils } from "../../Network/ProtobufClientUtils";
|
||||||
import { connectionManager } from "../../Connexion/ConnectionManager";
|
|
||||||
import type { RoomConnection } from "../../Connexion/RoomConnection";
|
import type { RoomConnection } from "../../Connexion/RoomConnection";
|
||||||
import { GlobalMessageManager } from "../../Administration/GlobalMessageManager";
|
|
||||||
import { userMessageManager } from "../../Administration/UserMessageManager";
|
|
||||||
import { Room } from "../../Connexion/Room";
|
import { Room } from "../../Connexion/Room";
|
||||||
import { jitsiFactory } from "../../WebRtc/JitsiFactory";
|
import { jitsiFactory } from "../../WebRtc/JitsiFactory";
|
||||||
import { urlManager } from "../../Url/UrlManager";
|
import { urlManager } from "../../Url/UrlManager";
|
||||||
import { audioManager } from "../../WebRtc/AudioManager";
|
import { audioManager } from "../../WebRtc/AudioManager";
|
||||||
import { TextureError } from "../../Exception/TextureError";
|
import { TextureError } from "../../Exception/TextureError";
|
||||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||||
import { iframeListener } from "../../Api/IframeListener";
|
|
||||||
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
import { HtmlUtils } from "../../WebRtc/HtmlUtils";
|
||||||
import { mediaManager } from "../../WebRtc/MediaManager";
|
import { mediaManager } from "../../WebRtc/MediaManager";
|
||||||
import { SimplePeer } from "../../WebRtc/SimplePeer";
|
import { SimplePeer } from "../../WebRtc/SimplePeer";
|
||||||
@ -70,8 +71,6 @@ import CanvasTexture = Phaser.Textures.CanvasTexture;
|
|||||||
import GameObject = Phaser.GameObjects.GameObject;
|
import GameObject = Phaser.GameObjects.GameObject;
|
||||||
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
|
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
|
||||||
import DOMElement = Phaser.GameObjects.DOMElement;
|
import DOMElement = Phaser.GameObjects.DOMElement;
|
||||||
import EVENT_TYPE = Phaser.Scenes.Events;
|
|
||||||
import type { Subscription } from "rxjs";
|
|
||||||
import { worldFullMessageStream } from "../../Connexion/WorldFullMessageStream";
|
import { worldFullMessageStream } from "../../Connexion/WorldFullMessageStream";
|
||||||
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
|
import { lazyLoadCompanionResource } from "../Companion/CompanionTexturesLoadingManager";
|
||||||
import { DirtyScene } from "./DirtyScene";
|
import { DirtyScene } from "./DirtyScene";
|
||||||
@ -81,6 +80,10 @@ import { PinchManager } from "../UserInput/PinchManager";
|
|||||||
import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick";
|
import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick";
|
||||||
import { waScaleManager } from "../Services/WaScaleManager";
|
import { waScaleManager } from "../Services/WaScaleManager";
|
||||||
import { EmoteManager } from "./EmoteManager";
|
import { EmoteManager } from "./EmoteManager";
|
||||||
|
import EVENT_TYPE = Phaser.Scenes.Events;
|
||||||
|
import RenderTexture = Phaser.GameObjects.RenderTexture;
|
||||||
|
import Tilemap = Phaser.Tilemaps.Tilemap;
|
||||||
|
import type { HasPlayerMovedEvent } from "../../Api/Events/HasPlayerMovedEvent";
|
||||||
|
|
||||||
import AnimatedTiles from "phaser-animated-tiles";
|
import AnimatedTiles from "phaser-animated-tiles";
|
||||||
import { StartPositionCalculator } from "./StartPositionCalculator";
|
import { StartPositionCalculator } from "./StartPositionCalculator";
|
||||||
@ -88,7 +91,6 @@ import { soundManager } from "./SoundManager";
|
|||||||
import { peerStore, screenSharingPeerStore } from "../../Stores/PeerStore";
|
import { peerStore, screenSharingPeerStore } from "../../Stores/PeerStore";
|
||||||
import { videoFocusStore } from "../../Stores/VideoFocusStore";
|
import { videoFocusStore } from "../../Stores/VideoFocusStore";
|
||||||
import { biggestAvailableAreaStore } from "../../Stores/BiggestAvailableAreaStore";
|
import { biggestAvailableAreaStore } from "../../Stores/BiggestAvailableAreaStore";
|
||||||
import type { HasPlayerMovedEvent } from "../../Api/Events/HasPlayerMovedEvent";
|
|
||||||
|
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
initPosition: PointInterface | null;
|
initPosition: PointInterface | null;
|
||||||
@ -196,6 +198,7 @@ export class GameScene extends DirtyScene {
|
|||||||
private pinchManager: PinchManager | undefined;
|
private pinchManager: PinchManager | undefined;
|
||||||
private mapTransitioning: boolean = false; //used to prevent transitions happenning at the same time.
|
private mapTransitioning: boolean = false; //used to prevent transitions happenning at the same time.
|
||||||
private emoteManager!: EmoteManager;
|
private emoteManager!: EmoteManager;
|
||||||
|
private preloading: boolean = true;
|
||||||
startPositionCalculator!: StartPositionCalculator;
|
startPositionCalculator!: StartPositionCalculator;
|
||||||
|
|
||||||
constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) {
|
constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) {
|
||||||
@ -279,11 +282,15 @@ export class GameScene extends DirtyScene {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.scene.start(ErrorSceneName, {
|
//once preloading is over, we don't want loading errors to crash the game, so we need to disable this behavior after preloading.
|
||||||
title: "Network error",
|
console.error("Error when loading: ", file);
|
||||||
subTitle: "An error occurred while loading resource:",
|
if (this.preloading) {
|
||||||
message: this.originalMapUrl ?? file.src,
|
this.scene.start(ErrorSceneName, {
|
||||||
});
|
title: "Network error",
|
||||||
|
subTitle: "An error occurred while loading resource:",
|
||||||
|
message: this.originalMapUrl ?? file.src,
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.load.scenePlugin("AnimatedTiles", AnimatedTiles, "animatedTiles", "animatedTiles");
|
this.load.scenePlugin("AnimatedTiles", AnimatedTiles, "animatedTiles", "animatedTiles");
|
||||||
this.load.on("filecomplete-tilemapJSON-" + this.MapUrlFile, (key: string, type: string, data: unknown) => {
|
this.load.on("filecomplete-tilemapJSON-" + this.MapUrlFile, (key: string, type: string, data: unknown) => {
|
||||||
@ -408,6 +415,7 @@ export class GameScene extends DirtyScene {
|
|||||||
|
|
||||||
//hook create scene
|
//hook create scene
|
||||||
create(): void {
|
create(): void {
|
||||||
|
this.preloading = false;
|
||||||
this.trackDirtyAnims();
|
this.trackDirtyAnims();
|
||||||
|
|
||||||
gameManager.gameSceneIsCreated(this);
|
gameManager.gameSceneIsCreated(this);
|
||||||
@ -1048,6 +1056,13 @@ ${escapedMessage}
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
this.iframeSubscriptionList.push(
|
||||||
|
iframeListener.setTilesStream.subscribe((eventTiles) => {
|
||||||
|
for (const eventTile of eventTiles) {
|
||||||
|
this.gameMap.putTile(eventTile.tile, eventTile.x, eventTile.y, eventTile.layer);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setPropertyLayer(
|
private setPropertyLayer(
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
import {EnableCameraSceneName} from "./EnableCameraScene";
|
import { EnableCameraSceneName } from "./EnableCameraScene";
|
||||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
import Rectangle = Phaser.GameObjects.Rectangle;
|
||||||
import {loadAllLayers} from "../Entity/PlayerTexturesLoadingManager";
|
import { loadAllLayers } from "../Entity/PlayerTexturesLoadingManager";
|
||||||
import Sprite = Phaser.GameObjects.Sprite;
|
import Sprite = Phaser.GameObjects.Sprite;
|
||||||
import {gameManager} from "../Game/GameManager";
|
import { gameManager } from "../Game/GameManager";
|
||||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||||
import {addLoader} from "../Components/Loader";
|
import { addLoader } from "../Components/Loader";
|
||||||
import type {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures";
|
import type { BodyResourceDescriptionInterface } from "../Entity/PlayerTextures";
|
||||||
import {AbstractCharacterScene} from "./AbstractCharacterScene";
|
import { AbstractCharacterScene } from "./AbstractCharacterScene";
|
||||||
import {areCharacterLayersValid} from "../../Connexion/LocalUser";
|
import { areCharacterLayersValid } from "../../Connexion/LocalUser";
|
||||||
import { SelectCharacterSceneName } from "./SelectCharacterScene";
|
import { SelectCharacterSceneName } from "./SelectCharacterScene";
|
||||||
import {customCharacterSceneVisibleStore} from "../../Stores/CustomCharacterStore";
|
import { activeRowStore, customCharacterSceneVisibleStore } from "../../Stores/CustomCharacterStore";
|
||||||
import {waScaleManager} from "../Services/WaScaleManager";
|
import { waScaleManager } from "../Services/WaScaleManager";
|
||||||
import {isMobile} from "../../Enum/EnvironmentVariable";
|
import { isMobile } from "../../Enum/EnvironmentVariable";
|
||||||
import {CustomizedCharacter} from "../Entity/CustomizedCharacter";
|
import { CustomizedCharacter } from "../Entity/CustomizedCharacter";
|
||||||
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
export const CustomizeSceneName = "CustomizeScene";
|
export const CustomizeSceneName = "CustomizeScene";
|
||||||
|
|
||||||
@ -21,7 +22,6 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
|
|
||||||
private selectedLayers: number[] = [0];
|
private selectedLayers: number[] = [0];
|
||||||
private containersRow: CustomizedCharacter[][] = [];
|
private containersRow: CustomizedCharacter[][] = [];
|
||||||
public activeRow:number = 0;
|
|
||||||
private layers: BodyResourceDescriptionInterface[][] = [];
|
private layers: BodyResourceDescriptionInterface[][] = [];
|
||||||
|
|
||||||
protected lazyloadingAttempt = true; //permit to update texture loaded after renderer
|
protected lazyloadingAttempt = true; //permit to update texture loaded after renderer
|
||||||
@ -31,16 +31,19 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
key: CustomizeSceneName
|
key: CustomizeSceneName,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
preload() {
|
preload() {
|
||||||
|
|
||||||
this.loadCustomSceneSelectCharacters().then((bodyResourceDescriptions) => {
|
this.loadCustomSceneSelectCharacters().then((bodyResourceDescriptions) => {
|
||||||
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
|
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
|
||||||
if(bodyResourceDescription.level == undefined || bodyResourceDescription.level < 0 || bodyResourceDescription.level > 5 ){
|
if (
|
||||||
throw 'Texture level is null';
|
bodyResourceDescription.level == undefined ||
|
||||||
|
bodyResourceDescription.level < 0 ||
|
||||||
|
bodyResourceDescription.level > 5
|
||||||
|
) {
|
||||||
|
throw "Texture level is null";
|
||||||
}
|
}
|
||||||
this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription);
|
this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription);
|
||||||
});
|
});
|
||||||
@ -50,14 +53,13 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
this.layers = loadAllLayers(this.load);
|
this.layers = loadAllLayers(this.load);
|
||||||
this.lazyloadingAttempt = false;
|
this.lazyloadingAttempt = false;
|
||||||
|
|
||||||
|
|
||||||
//this function must stay at the end of preload function
|
//this function must stay at the end of preload function
|
||||||
addLoader(this);
|
addLoader(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
create() {
|
create() {
|
||||||
customCharacterSceneVisibleStore.set(true);
|
customCharacterSceneVisibleStore.set(true);
|
||||||
this.events.addListener('wake', () => {
|
this.events.addListener("wake", () => {
|
||||||
waScaleManager.saveZoom();
|
waScaleManager.saveZoom();
|
||||||
waScaleManager.zoomModifier = isMobile() ? 3 : 1;
|
waScaleManager.zoomModifier = isMobile() ? 3 : 1;
|
||||||
customCharacterSceneVisibleStore.set(true);
|
customCharacterSceneVisibleStore.set(true);
|
||||||
@ -66,8 +68,13 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
waScaleManager.saveZoom();
|
waScaleManager.saveZoom();
|
||||||
waScaleManager.zoomModifier = isMobile() ? 3 : 1;
|
waScaleManager.zoomModifier = isMobile() ? 3 : 1;
|
||||||
|
|
||||||
this.Rectangle = this.add.rectangle(this.cameras.main.worldView.x + this.cameras.main.width / 2, this.cameras.main.worldView.y + this.cameras.main.height / 3, 32, 33)
|
this.Rectangle = this.add.rectangle(
|
||||||
this.Rectangle.setStrokeStyle(2, 0xFFFFFF);
|
this.cameras.main.worldView.x + this.cameras.main.width / 2,
|
||||||
|
this.cameras.main.worldView.y + this.cameras.main.height / 3,
|
||||||
|
32,
|
||||||
|
33
|
||||||
|
);
|
||||||
|
this.Rectangle.setStrokeStyle(2, 0xffffff);
|
||||||
this.add.existing(this.Rectangle);
|
this.add.existing(this.Rectangle);
|
||||||
|
|
||||||
this.createCustomizeLayer(0, 0, 0);
|
this.createCustomizeLayer(0, 0, 0);
|
||||||
@ -78,24 +85,24 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
this.createCustomizeLayer(0, 0, 5);
|
this.createCustomizeLayer(0, 0, 5);
|
||||||
|
|
||||||
this.moveLayers();
|
this.moveLayers();
|
||||||
this.input.keyboard.on('keyup-ENTER', () => {
|
this.input.keyboard.on("keyup-ENTER", () => {
|
||||||
this.nextSceneToCamera();
|
this.nextSceneToCamera();
|
||||||
});
|
});
|
||||||
this.input.keyboard.on('keyup-BACKSPACE', () => {
|
this.input.keyboard.on("keyup-BACKSPACE", () => {
|
||||||
this.backToPreviousScene();
|
this.backToPreviousScene();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Note: the key bindings are not directly put on the moveCursorVertically or moveCursorHorizontally methods
|
// Note: the key bindings are not directly put on the moveCursorVertically or moveCursorHorizontally methods
|
||||||
// because if 2 such events are fired close to one another, it makes the whole application crawl to a halt (for a reason I cannot
|
// because if 2 such events are fired close to one another, it makes the whole application crawl to a halt (for a reason I cannot
|
||||||
// explain, the list of sprites managed by the update list become immense
|
// explain, the list of sprites managed by the update list become immense
|
||||||
this.input.keyboard.on('keyup-RIGHT', () => this.moveHorizontally = 1);
|
this.input.keyboard.on("keyup-RIGHT", () => (this.moveHorizontally = 1));
|
||||||
this.input.keyboard.on('keyup-LEFT', () => this.moveHorizontally = -1);
|
this.input.keyboard.on("keyup-LEFT", () => (this.moveHorizontally = -1));
|
||||||
this.input.keyboard.on('keyup-DOWN', () => this.moveVertically = 1);
|
this.input.keyboard.on("keyup-DOWN", () => (this.moveVertically = 1));
|
||||||
this.input.keyboard.on('keyup-UP', () => this.moveVertically = -1);
|
this.input.keyboard.on("keyup-UP", () => (this.moveVertically = -1));
|
||||||
|
|
||||||
const customCursorPosition = localUserStore.getCustomCursorPosition();
|
const customCursorPosition = localUserStore.getCustomCursorPosition();
|
||||||
if (customCursorPosition) {
|
if (customCursorPosition) {
|
||||||
this.activeRow = customCursorPosition.activeRow;
|
activeRowStore.set(customCursorPosition.activeRow);
|
||||||
this.selectedLayers = customCursorPosition.selectedLayers;
|
this.selectedLayers = customCursorPosition.selectedLayers;
|
||||||
this.moveLayers();
|
this.moveLayers();
|
||||||
this.updateSelectedLayer();
|
this.updateSelectedLayer();
|
||||||
@ -113,31 +120,30 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private doMoveCursorHorizontally(index: number): void {
|
private doMoveCursorHorizontally(index: number): void {
|
||||||
this.selectedLayers[this.activeRow] += index;
|
this.selectedLayers[get(activeRowStore)] += index;
|
||||||
if (this.selectedLayers[this.activeRow] < 0) {
|
if (this.selectedLayers[get(activeRowStore)] < 0) {
|
||||||
this.selectedLayers[this.activeRow] = 0
|
this.selectedLayers[get(activeRowStore)] = 0;
|
||||||
} else if(this.selectedLayers[this.activeRow] > this.layers[this.activeRow].length - 1) {
|
} else if (this.selectedLayers[get(activeRowStore)] > this.layers[get(activeRowStore)].length - 1) {
|
||||||
this.selectedLayers[this.activeRow] = this.layers[this.activeRow].length - 1
|
this.selectedLayers[get(activeRowStore)] = this.layers[get(activeRowStore)].length - 1;
|
||||||
}
|
}
|
||||||
this.moveLayers();
|
this.moveLayers();
|
||||||
this.updateSelectedLayer();
|
this.updateSelectedLayer();
|
||||||
this.saveInLocalStorage();
|
this.saveInLocalStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private doMoveCursorVertically(index:number): void {
|
private doMoveCursorVertically(index: number): void {
|
||||||
|
activeRowStore.set(get(activeRowStore) + index);
|
||||||
this.activeRow += index;
|
if (get(activeRowStore) < 0) {
|
||||||
if (this.activeRow < 0) {
|
activeRowStore.set(0);
|
||||||
this.activeRow = 0
|
} else if (get(activeRowStore) > this.layers.length - 1) {
|
||||||
} else if (this.activeRow > this.layers.length - 1) {
|
activeRowStore.set(this.layers.length - 1);
|
||||||
this.activeRow = this.layers.length - 1
|
|
||||||
}
|
}
|
||||||
this.moveLayers();
|
this.moveLayers();
|
||||||
this.saveInLocalStorage();
|
this.saveInLocalStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private saveInLocalStorage() {
|
private saveInLocalStorage() {
|
||||||
localUserStore.setCustomCursorPosition(this.activeRow, this.selectedLayers);
|
localUserStore.setCustomCursorPosition(get(activeRowStore), this.selectedLayers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -173,7 +179,7 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
* @param selectedItem, The number of the item select (0 for black body...)
|
* @param selectedItem, The number of the item select (0 for black body...)
|
||||||
*/
|
*/
|
||||||
private generateCharacter(x: number, y: number, layerNumber: number, selectedItem: number) {
|
private generateCharacter(x: number, y: number, layerNumber: number, selectedItem: number) {
|
||||||
return new CustomizedCharacter(this, x, y, this.getContainerChildren(layerNumber,selectedItem));
|
return new CustomizedCharacter(this, x, y, this.getContainerChildren(layerNumber, selectedItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
private getContainerChildren(layerNumber: number, selectedItem: number): Array<string> {
|
private getContainerChildren(layerNumber: number, selectedItem: number): Array<string> {
|
||||||
@ -188,7 +194,7 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
}
|
}
|
||||||
children.push(this.layers[j][layer].name);
|
children.push(this.layers[j][layer].name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,17 +208,16 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
const screenHeight = this.game.renderer.height;
|
const screenHeight = this.game.renderer.height;
|
||||||
for (let i = 0; i < this.containersRow.length; i++) {
|
for (let i = 0; i < this.containersRow.length; i++) {
|
||||||
for (let j = 0; j < this.containersRow[i].length; j++) {
|
for (let j = 0; j < this.containersRow[i].length; j++) {
|
||||||
let selectedX = this.selectedLayers[i];
|
let selectedX = this.selectedLayers[i];
|
||||||
if (selectedX === undefined) {
|
if (selectedX === undefined) {
|
||||||
selectedX = 0;
|
selectedX = 0;
|
||||||
}
|
}
|
||||||
this.containersRow[i][j].x = screenCenterX + (j - selectedX) * 40;
|
this.containersRow[i][j].x = screenCenterX + (j - selectedX) * 40;
|
||||||
this.containersRow[i][j].y = screenCenterY + (i - this.activeRow) * 40;
|
this.containersRow[i][j].y = screenCenterY + (i - get(activeRowStore)) * 40;
|
||||||
const alpha1 = Math.abs(selectedX - j)*47*2/screenWidth;
|
const alpha1 = (Math.abs(selectedX - j) * 47 * 2) / screenWidth;
|
||||||
const alpha2 = Math.abs(this.activeRow - i)*49*2/screenHeight;
|
const alpha2 = (Math.abs(get(activeRowStore) - i) * 49 * 2) / screenHeight;
|
||||||
this.containersRow[i][j].setAlpha((1 -alpha1)*(1 - alpha2));
|
this.containersRow[i][j].setAlpha((1 - alpha1) * (1 - alpha2));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,8 +233,8 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private updateSelectedLayer() {
|
private updateSelectedLayer() {
|
||||||
for(let i = 0; i < this.containersRow.length; i++){
|
for (let i = 0; i < this.containersRow.length; i++) {
|
||||||
for(let j = 0; j < this.containersRow[i].length; j++){
|
for (let j = 0; j < this.containersRow[i].length; j++) {
|
||||||
const children = this.getContainerChildren(i, j);
|
const children = this.getContainerChildren(i, j);
|
||||||
this.containersRow[i][j].updateSprites(children);
|
this.containersRow[i][j].updateSprites(children);
|
||||||
}
|
}
|
||||||
@ -237,8 +242,7 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update(time: number, delta: number): void {
|
update(time: number, delta: number): void {
|
||||||
|
if (this.lazyloadingAttempt) {
|
||||||
if(this.lazyloadingAttempt){
|
|
||||||
this.moveLayers();
|
this.moveLayers();
|
||||||
this.lazyloadingAttempt = false;
|
this.lazyloadingAttempt = false;
|
||||||
}
|
}
|
||||||
@ -253,38 +257,35 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public onResize(): void {
|
||||||
|
|
||||||
|
|
||||||
public onResize(): void {
|
|
||||||
this.moveLayers();
|
this.moveLayers();
|
||||||
|
|
||||||
this.Rectangle.x = this.cameras.main.worldView.x + this.cameras.main.width / 2;
|
this.Rectangle.x = this.cameras.main.worldView.x + this.cameras.main.width / 2;
|
||||||
this.Rectangle.y = this.cameras.main.worldView.y + this.cameras.main.height / 3;
|
this.Rectangle.y = this.cameras.main.worldView.y + this.cameras.main.height / 3;
|
||||||
}
|
|
||||||
|
|
||||||
public nextSceneToCamera(){
|
|
||||||
const layers: string[] = [];
|
|
||||||
let i = 0;
|
|
||||||
for (const layerItem of this.selectedLayers) {
|
|
||||||
if (layerItem !== undefined) {
|
|
||||||
layers.push(this.layers[i][layerItem].name);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (!areCharacterLayersValid(layers)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gameManager.setCharacterLayers(layers);
|
|
||||||
this.scene.sleep(CustomizeSceneName);
|
|
||||||
waScaleManager.restoreZoom();
|
|
||||||
this.events.removeListener('wake');
|
|
||||||
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
|
||||||
customCharacterSceneVisibleStore.set(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public backToPreviousScene(){
|
public nextSceneToCamera() {
|
||||||
|
const layers: string[] = [];
|
||||||
|
let i = 0;
|
||||||
|
for (const layerItem of this.selectedLayers) {
|
||||||
|
if (layerItem !== undefined) {
|
||||||
|
layers.push(this.layers[i][layerItem].name);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (!areCharacterLayersValid(layers)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gameManager.setCharacterLayers(layers);
|
||||||
|
this.scene.sleep(CustomizeSceneName);
|
||||||
|
waScaleManager.restoreZoom();
|
||||||
|
this.events.removeListener("wake");
|
||||||
|
gameManager.tryResumingGame(this, EnableCameraSceneName);
|
||||||
|
customCharacterSceneVisibleStore.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public backToPreviousScene() {
|
||||||
this.scene.sleep(CustomizeSceneName);
|
this.scene.sleep(CustomizeSceneName);
|
||||||
waScaleManager.restoreZoom();
|
waScaleManager.restoreZoom();
|
||||||
this.scene.run(SelectCharacterSceneName);
|
this.scene.run(SelectCharacterSceneName);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
import { derived, writable, Writable } from "svelte/store";
|
import { derived, writable, Writable } from "svelte/store";
|
||||||
|
|
||||||
export const customCharacterSceneVisibleStore = writable(false);
|
export const customCharacterSceneVisibleStore = writable(false);
|
||||||
|
|
||||||
|
export const activeRowStore = writable(0);
|
||||||
|
@ -16,6 +16,7 @@ import player from "./Api/iframe/player";
|
|||||||
import type { ButtonDescriptor } from "./Api/iframe/Ui/ButtonDescriptor";
|
import type { ButtonDescriptor } from "./Api/iframe/Ui/ButtonDescriptor";
|
||||||
import type { Popup } from "./Api/iframe/Ui/Popup";
|
import type { Popup } from "./Api/iframe/Ui/Popup";
|
||||||
import type { Sound } from "./Api/iframe/Sound/Sound";
|
import type { Sound } from "./Api/iframe/Sound/Sound";
|
||||||
|
import { sendToWorkadventure } from "./Api/iframe/IframeApiContribution";
|
||||||
|
|
||||||
const wa = {
|
const wa = {
|
||||||
ui,
|
ui,
|
||||||
@ -36,6 +37,7 @@ const wa = {
|
|||||||
console.warn("Method WA.sendChatMessage is deprecated. Please use WA.chat.sendChatMessage instead");
|
console.warn("Method WA.sendChatMessage is deprecated. Please use WA.chat.sendChatMessage instead");
|
||||||
chat.sendChatMessage(message, author);
|
chat.sendChatMessage(message, author);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use WA.chat.disablePlayerControls instead
|
* @deprecated Use WA.chat.disablePlayerControls instead
|
||||||
*/
|
*/
|
||||||
@ -107,9 +109,9 @@ const wa = {
|
|||||||
/**
|
/**
|
||||||
* @deprecated Use WA.nav.openCoWebSite instead
|
* @deprecated Use WA.nav.openCoWebSite instead
|
||||||
*/
|
*/
|
||||||
openCoWebSite(url: string): void {
|
openCoWebSite(url: string, allowApi: boolean = false, allowPolicy: string = ""): void {
|
||||||
console.warn("Method WA.openCoWebSite is deprecated. Please use WA.nav.openCoWebSite instead");
|
console.warn("Method WA.openCoWebSite is deprecated. Please use WA.nav.openCoWebSite instead");
|
||||||
nav.openCoWebSite(url);
|
nav.openCoWebSite(url, allowApi, allowPolicy);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,14 +10,18 @@ import NodePolyfillPlugin from "node-polyfill-webpack-plugin";
|
|||||||
import { DISPLAY_TERMS_OF_USE } from "./src/Enum/EnvironmentVariable";
|
import { DISPLAY_TERMS_OF_USE } from "./src/Enum/EnvironmentVariable";
|
||||||
|
|
||||||
const mode = process.env.NODE_ENV ?? "development";
|
const mode = process.env.NODE_ENV ?? "development";
|
||||||
|
const buildNpmTypingsForApi = !!process.env.BUILD_TYPINGS;
|
||||||
const isProduction = mode === "production";
|
const isProduction = mode === "production";
|
||||||
const isDevelopment = !isProduction;
|
const isDevelopment = !isProduction;
|
||||||
|
|
||||||
|
const entries: { [key: string]: string } = {};
|
||||||
|
if (!buildNpmTypingsForApi) {
|
||||||
|
entries.main = "./src/index.ts";
|
||||||
|
}
|
||||||
|
entries.iframe_api = "./src/iframe_api.ts";
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: {
|
entry: entries,
|
||||||
main: "./src/index.ts",
|
|
||||||
iframe_api: "./src/iframe_api.ts",
|
|
||||||
},
|
|
||||||
mode: mode,
|
mode: mode,
|
||||||
devtool: isDevelopment ? "inline-source-map" : "source-map",
|
devtool: isDevelopment ? "inline-source-map" : "source-map",
|
||||||
devServer: {
|
devServer: {
|
||||||
@ -38,7 +42,10 @@ module.exports = {
|
|||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
loader: "ts-loader",
|
loader: "ts-loader",
|
||||||
options: {
|
options: {
|
||||||
transpileOnly: true,
|
transpileOnly: !buildNpmTypingsForApi,
|
||||||
|
compilerOptions: {
|
||||||
|
declaration: buildNpmTypingsForApi,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
18
maps/tests/Metadata/cowebsiteAllowApi.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<script>
|
||||||
|
var script = document.createElement('script');
|
||||||
|
// Don't do this at home kids! The "document.referrer" part is actually inserting a XSS security.
|
||||||
|
// We are OK in this precise case because the HTML page is hosted on the "maps" domain that contains only static files.
|
||||||
|
script.setAttribute('src', document.referrer + 'iframe_api.js');
|
||||||
|
document.head.appendChild(script);
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
WA.chat.sendChatMessage('The iframe opened by a script works !', 'Mr Robot');
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Website opened by script.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
1
maps/tests/Metadata/cowebsiteAllowApi.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
WA.nav.openCoWebSite("cowebsiteAllowApi.html", true, "");
|
98
maps/tests/Metadata/cowebsiteAllowApi.json
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":10,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":2,
|
||||||
|
"name":"start",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[33, 34, 34, 34, 34, 34, 34, 34, 34, 35, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 49, 50, 50, 50, 50, 50, 50, 50, 50, 51],
|
||||||
|
"height":10,
|
||||||
|
"id":1,
|
||||||
|
"name":"bottom",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":3,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[
|
||||||
|
{
|
||||||
|
"height":116.5,
|
||||||
|
"id":1,
|
||||||
|
"name":"",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"text":"Test : \nThe iframe is opened by script.\n\nResult : \nA message is send to the chat.",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":295.875,
|
||||||
|
"x":11.8125,
|
||||||
|
"y":188.5
|
||||||
|
}],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 0, 0, 0, 16, 16, 16, 0, 0, 16, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 16, 16, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 16, 16, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":4,
|
||||||
|
"name":"mushroom",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":5,
|
||||||
|
"nextobjectid":2,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"script",
|
||||||
|
"type":"string",
|
||||||
|
"value":"cowebsiteAllowApi.js"
|
||||||
|
}],
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.4.3",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":8,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"tileset_dungeon.png",
|
||||||
|
"imageheight":256,
|
||||||
|
"imagewidth":256,
|
||||||
|
"margin":0,
|
||||||
|
"name":"tileset_dungeon",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":64,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":1.4,
|
||||||
|
"width":10
|
||||||
|
}
|
230
maps/tests/Metadata/map.json
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":10,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":1,
|
||||||
|
"name":"start",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 33, 34, 34, 34, 34, 34, 34, 35, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 41, 42, 42, 42, 42, 42, 42, 43, 46, 46, 49, 50, 50, 50, 50, 50, 50, 51, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46],
|
||||||
|
"height":10,
|
||||||
|
"id":2,
|
||||||
|
"name":"bottom",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 52, 52, 0, 0, 0, 0, 0, 0, 0, 52, 52, 52, 0, 0, 0, 0, 0, 0, 0, 52, 52, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":4,
|
||||||
|
"name":"metadata",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":5,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19],
|
||||||
|
"height":10,
|
||||||
|
"id":3,
|
||||||
|
"name":"wall",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":6,
|
||||||
|
"nextobjectid":1,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"script",
|
||||||
|
"type":"string",
|
||||||
|
"value":"script.js"
|
||||||
|
}],
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.4.3",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":8,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"tileset_dungeon.png",
|
||||||
|
"imageheight":256,
|
||||||
|
"imagewidth":256,
|
||||||
|
"margin":0,
|
||||||
|
"name":"TDungeon",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":64,
|
||||||
|
"tileheight":32,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":0,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":2,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":3,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":4,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":8,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":9,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":10,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":11,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":12,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":16,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":17,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":18,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":19,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":20,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":1.4,
|
||||||
|
"width":10
|
||||||
|
}
|
9
maps/tests/Metadata/script.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
|
||||||
|
/*WA.getMapUrl().then((map) => {console.log('mapUrl : ', map)});
|
||||||
|
WA.getUuid().then((uuid) => {console.log('Uuid : ',uuid)});
|
||||||
|
WA.getRoomId().then((roomId) => console.log('roomID : ',roomId));*/
|
||||||
|
|
||||||
|
//WA.onPlayerMove(console.log);
|
||||||
|
WA.setProperty('metadata', 'openWebsite', 'https://fr.wikipedia.org/');
|
||||||
|
WA.getDataLayer().then((data) => {console.log('data 1 : ', data)});
|
31
maps/tests/Metadata/setTiles.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<script>
|
||||||
|
var script = document.createElement('script');
|
||||||
|
// Don't do this at home kids! The "document.referrer" part is actually inserting a XSS security.
|
||||||
|
// We are OK in this precise case because the HTML page is hosted on the "maps" domain that contains only static files.
|
||||||
|
script.setAttribute('src', document.referrer + 'iframe_api.js');
|
||||||
|
document.head.appendChild(script);
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
WA.room.setTiles([
|
||||||
|
{x: 0, y: 0, tile: 92, layer: 'setTiles'},
|
||||||
|
{x: 0, y: 2, tile: 'Red', layer: 'setTiles'},
|
||||||
|
{x: 0, y: 3, tile: 99, layer: 'setTiles'},
|
||||||
|
{x: 0, y: 5, tile: 117, layer: 'setTiles'},
|
||||||
|
{x: 0, y: 6, tile: 117, layer: 'setTiles'},
|
||||||
|
{x: 0, y: 9, tile: 74, layer: 'setTiles'}
|
||||||
|
]);
|
||||||
|
WA.room.setTiles([
|
||||||
|
{x: 6, y: 4, tile: 'blue', layer: 'setTiles'},
|
||||||
|
{x: 7, y: 4, tile: 109, layer: 'setTiles'},
|
||||||
|
{x: 8, y: 4, tile: 109, layer: 'setTiles'},
|
||||||
|
{x: 9, y: 4, tile: 'blue', layer: 'setTiles'}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
348
maps/tests/Metadata/setTiles.json
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
{ "compressionlevel":-1,
|
||||||
|
"editorsettings":
|
||||||
|
{
|
||||||
|
"export":
|
||||||
|
{
|
||||||
|
"target":"."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"height":10,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":1,
|
||||||
|
"name":"start",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[33, 34, 34, 34, 34, 34, 34, 34, 34, 35, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 49, 50, 50, 50, 50, 50, 50, 50, 50, 51],
|
||||||
|
"height":10,
|
||||||
|
"id":2,
|
||||||
|
"name":"bottom",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":4,
|
||||||
|
"name":"metadata",
|
||||||
|
"opacity":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"openWebsite",
|
||||||
|
"type":"string",
|
||||||
|
"value":"setTiles.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"openWebsiteAllowApi",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}],
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 65, 65, 65, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":8,
|
||||||
|
"name":"setTiles",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":5,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[
|
||||||
|
{
|
||||||
|
"height":191.866671635267,
|
||||||
|
"id":1,
|
||||||
|
"name":"",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"fontfamily":"Sans Serif",
|
||||||
|
"pixelsize":9,
|
||||||
|
"text":"Test : \nWalk on the grass\n\nResult : \nThe Yellow Tile opens a Jitsi with Trigger.\n\nThe Red Tile opens cowebsite Wikipedia. The highest Red Tile is found by 'name' property index, the lowest by 'number' index.\n\nThe White Tiles are silent tiles. You cannot open a bubble in it. (Even if the other player didn't activate the script.)\n\nThe Pale Tile (Lowest) is an exitUrl tile to customMenu.json.\n\nThe Blue Tile are 'collides' tile. The two tiles in the center are 'number' index. The others are 'name' property index.\n",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":274.674838251912,
|
||||||
|
"x":32.5473600365393,
|
||||||
|
"y":128.305680721763
|
||||||
|
}],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":9,
|
||||||
|
"nextobjectid":2,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.4.3",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":8,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"tileset_dungeon.png",
|
||||||
|
"imageheight":256,
|
||||||
|
"imagewidth":256,
|
||||||
|
"margin":0,
|
||||||
|
"name":"TDungeon",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":64,
|
||||||
|
"tileheight":32,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":0,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":2,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":3,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":4,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":8,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":9,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":10,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":11,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":12,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":16,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":17,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":18,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":19,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":20,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"tilewidth":32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns":8,
|
||||||
|
"firstgid":65,
|
||||||
|
"image":"floortileset.png",
|
||||||
|
"imageheight":288,
|
||||||
|
"imagewidth":256,
|
||||||
|
"margin":0,
|
||||||
|
"name":"Floor",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":72,
|
||||||
|
"tileheight":32,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":9,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"exitUrl",
|
||||||
|
"type":"string",
|
||||||
|
"value":"customMenu.json"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":27,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"jitsiRoom",
|
||||||
|
"type":"string",
|
||||||
|
"value":"TEST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"jitsiTrigger",
|
||||||
|
"type":"string",
|
||||||
|
"value":"onaction"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"jitsiUrl",
|
||||||
|
"type":"string",
|
||||||
|
"value":"meet.jit.si"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":34,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"name",
|
||||||
|
"type":"string",
|
||||||
|
"value":"Red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"openWebsite",
|
||||||
|
"type":"string",
|
||||||
|
"value":"https:\/\/fr.wikipedia.org\/wiki\/Wikip%C3%A9dia:Accueil_principal"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":40,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"name",
|
||||||
|
"type":"string",
|
||||||
|
"value":""
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":44,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"name",
|
||||||
|
"type":"string",
|
||||||
|
"value":"blue"
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":52,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"silent",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":1.4,
|
||||||
|
"width":10
|
||||||
|
}
|
@ -1,22 +1,30 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<script src="http://play.workadventure.localhost/iframe_api.js"></script>
|
<script>
|
||||||
|
var script = document.createElement('script');
|
||||||
|
// Don't do this at home kids! The "document.referrer" part is actually inserting a XSS security.
|
||||||
|
// We are OK in this precise case because the HTML page is hosted on the "maps" domain that contains only static files.
|
||||||
|
script.setAttribute('src', document.referrer + 'iframe_api.js');
|
||||||
|
document.head.appendChild(script);
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<button id="sendchat">Send chat message</button>
|
<button id="sendchat">Send chat message</button>
|
||||||
<script>
|
<script>
|
||||||
document.getElementById('sendchat').onclick = () => {
|
document.getElementById('sendchat').onclick = () => {
|
||||||
WA.sendChatMessage('Hello world!', 'Mr ROBOT');
|
WA.chat.sendChatMessage('Hello world!', 'Mr ROBOT');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<div id="chatSent"></div>
|
<div id="chatSent"></div>
|
||||||
<script>
|
<script>
|
||||||
WA.onChatMessage((message => {
|
window.addEventListener('load', () => {
|
||||||
const chatDiv = document.createElement('p');
|
WA.chat.onChatMessage((message => {
|
||||||
chatDiv.innerText = message;
|
const chatDiv = document.createElement('p');
|
||||||
document.getElementById('chatSent').append(chatDiv);
|
chatDiv.innerText = message;
|
||||||
}));
|
document.getElementById('chatSent').append(chatDiv);
|
||||||
|
}));
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<label>Base test URL:</label>
|
<label>Base test URL:</label>
|
||||||
<input id="baseurl" type="text" value="http://play.workadventure.localhost/_/global/maps.workadventure.localhost/tests/" />
|
<input id="baseurl" type="text" value="" />
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Result</th>
|
<th>Result</th>
|
||||||
@ -106,6 +106,14 @@
|
|||||||
<a href="#" class="testLink" data-testmap="help_camera_setting.json" target="_blank">Test the HelpCameraSettingScene</a>
|
<a href="#" class="testLink" data-testmap="help_camera_setting.json" target="_blank">Test the HelpCameraSettingScene</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="radio" name="test-cowebsite-allowAPI"> Success <input type="radio" name="test-cowebsite-allowAPI"> Failure <input type="radio" name="test-cowebsite-allowAPI" checked> Pending
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="#" class="testLink" data-testmap="Metadata/cowebsiteAllowApi.json" target="_blank">Test a iframe opened by a script can use Iframe API</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<input type="radio" name="test-custom-menu"> Success <input type="radio" name="test-custom-menu"> Failure <input type="radio" name="test-custom-menu" checked> Pending
|
<input type="radio" name="test-custom-menu"> Success <input type="radio" name="test-custom-menu"> Failure <input type="radio" name="test-custom-menu" checked> Pending
|
||||||
@ -178,10 +186,41 @@
|
|||||||
<a href="#" class="testLink" data-testmap="start-tile.json#S2" target="_blank">Test start tile (S2)</a>
|
<a href="#" class="testLink" data-testmap="start-tile.json#S2" target="_blank">Test start tile (S2)</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="radio" name="test-cowebsite-allowAPI"> Success <input type="radio" name="test-cowebsite-allowAPI"> Failure <input type="radio" name="test-cowebsite-allowAPI" checked> Pending
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="#" class="testLink" data-testmap="Metadata/cowebsiteAllowApi.json" target="_blank">Test cowebsite opened by script is allowed to use IFrame API</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="radio" name="test-set-tiles"> Success <input type="radio" name="test-set-tiles"> Failure <input type="radio" name="test-set-tiles" checked> Pending
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="#" class="testLink" data-testmap="Metadata/setTiles.json" target="_blank">Test set tiles</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const baseInput = document.getElementById('baseurl');
|
const baseInput = document.getElementById('baseurl');
|
||||||
|
|
||||||
|
let host = window.location.host;
|
||||||
|
let playHost;
|
||||||
|
if (host.startsWith('maps-')) {
|
||||||
|
playHost = 'play-'+host.substr(5);
|
||||||
|
} else if (host.startsWith('maps.')) {
|
||||||
|
playHost = 'play.'+host.substr(5);
|
||||||
|
} else {
|
||||||
|
playHost = 'localhost';
|
||||||
|
}
|
||||||
|
|
||||||
|
let completeUrl = window.location.protocol + '//' + playHost + '/_/global/' + host + window.location.pathname;
|
||||||
|
|
||||||
|
baseInput.value = completeUrl;
|
||||||
|
|
||||||
baseInput.addEventListener('change', init);
|
baseInput.addEventListener('change', init);
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
husky@^6.0.0:
|
"husky@^6.0.0":
|
||||||
version "6.0.0"
|
"resolved" "https://registry.npmjs.org/husky/-/husky-6.0.0.tgz"
|
||||||
resolved "https://registry.yarnpkg.com/husky/-/husky-6.0.0.tgz#810f11869adf51604c32ea577edbc377d7f9319e"
|
"version" "6.0.0"
|
||||||
|