Merge pull request #1702 from thecodingmachine/develop
Deploy 2022-01-04
This commit is contained in:
commit
88509916a8
2
.github/workflows/continuous_integration.yml
vendored
2
.github/workflows/continuous_integration.yml
vendored
@ -39,7 +39,7 @@ jobs:
|
|||||||
working-directory: "messages"
|
working-directory: "messages"
|
||||||
|
|
||||||
- name: "Build proto messages"
|
- name: "Build proto messages"
|
||||||
run: yarn run proto && yarn run copy-to-front && yarn run json-copy-to-front
|
run: yarn run ts-proto && yarn run copy-to-front-ts-proto && yarn run json-copy-to-front
|
||||||
working-directory: "messages"
|
working-directory: "messages"
|
||||||
|
|
||||||
- name: "Create index.html"
|
- name: "Create index.html"
|
||||||
|
3
.github/workflows/end_to_end_tests.yml
vendored
3
.github/workflows/end_to_end_tests.yml
vendored
@ -12,6 +12,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
start-runner:
|
start-runner:
|
||||||
|
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false)
|
||||||
name: Start self-hosted EC2 runner
|
name: Start self-hosted EC2 runner
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
@ -109,12 +110,14 @@ jobs:
|
|||||||
if: ${{ always() }} # required to stop the runner even if the error happened in the previous jobs
|
if: ${{ always() }} # required to stop the runner even if the error happened in the previous jobs
|
||||||
steps:
|
steps:
|
||||||
- name: Configure AWS credentials
|
- name: Configure AWS credentials
|
||||||
|
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false)
|
||||||
uses: aws-actions/configure-aws-credentials@v1
|
uses: aws-actions/configure-aws-credentials@v1
|
||||||
with:
|
with:
|
||||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
aws-region: ${{ secrets.AWS_REGION }}
|
aws-region: ${{ secrets.AWS_REGION }}
|
||||||
- name: Stop EC2 runner
|
- name: Stop EC2 runner
|
||||||
|
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false)
|
||||||
uses: machulav/ec2-github-runner@v2
|
uses: machulav/ec2-github-runner@v2
|
||||||
with:
|
with:
|
||||||
mode: stop
|
mode: stop
|
||||||
|
2
.github/workflows/push-to-npm.yml
vendored
2
.github/workflows/push-to-npm.yml
vendored
@ -36,7 +36,7 @@ jobs:
|
|||||||
working-directory: "messages"
|
working-directory: "messages"
|
||||||
|
|
||||||
- name: "Build proto messages"
|
- name: "Build proto messages"
|
||||||
run: yarn run proto && yarn run copy-to-front && yarn run json-copy-to-front
|
run: yarn run ts-proto && yarn run copy-to-front-ts-proto && yarn run json-copy-to-front
|
||||||
working-directory: "messages"
|
working-directory: "messages"
|
||||||
|
|
||||||
- name: "Create index.html"
|
- name: "Create index.html"
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
// lib/server.ts
|
// lib/server.ts
|
||||||
import App from "./src/App";
|
import App from "./src/App";
|
||||||
import grpc from "grpc";
|
import grpc from "grpc";
|
||||||
import {roomManager} from "./src/RoomManager";
|
import { roomManager } from "./src/RoomManager";
|
||||||
import {IRoomManagerServer, RoomManagerService} from "./src/Messages/generated/messages_grpc_pb";
|
import { IRoomManagerServer, RoomManagerService } from "./src/Messages/generated/messages_grpc_pb";
|
||||||
import {HTTP_PORT, GRPC_PORT} from "./src/Enum/EnvironmentVariable";
|
import { HTTP_PORT, GRPC_PORT } from "./src/Enum/EnvironmentVariable";
|
||||||
|
|
||||||
App.listen(HTTP_PORT, () => console.log(`WorkAdventure HTTP API starting on port %d!`, HTTP_PORT))
|
App.listen(HTTP_PORT, () => console.log(`WorkAdventure HTTP API starting on port %d!`, HTTP_PORT));
|
||||||
|
|
||||||
const server = new grpc.Server();
|
const server = new grpc.Server();
|
||||||
server.addService<IRoomManagerServer>(RoomManagerService, roomManager);
|
server.addService<IRoomManagerServer>(RoomManagerService, roomManager);
|
||||||
|
|
||||||
server.bind(`0.0.0.0:${GRPC_PORT}`, grpc.ServerCredentials.createInsecure());
|
server.bind(`0.0.0.0:${GRPC_PORT}`, grpc.ServerCredentials.createInsecure());
|
||||||
server.start();
|
server.start();
|
||||||
console.log('WorkAdventure HTTP/2 API starting on port %d!', GRPC_PORT);
|
console.log("WorkAdventure HTTP/2 API starting on port %d!", GRPC_PORT);
|
||||||
|
@ -106,11 +106,6 @@ const roomManager: IRoomManagerServer = {
|
|||||||
user,
|
user,
|
||||||
message.getWebrtcscreensharingsignaltoservermessage() as WebRtcSignalToServerMessage
|
message.getWebrtcscreensharingsignaltoservermessage() as WebRtcSignalToServerMessage
|
||||||
);
|
);
|
||||||
} else if (message.hasPlayglobalmessage()) {
|
|
||||||
socketManager.emitPlayGlobalMessage(
|
|
||||||
room,
|
|
||||||
message.getPlayglobalmessage() as PlayGlobalMessage
|
|
||||||
);
|
|
||||||
} else if (message.hasQueryjitsijwtmessage()) {
|
} else if (message.hasQueryjitsijwtmessage()) {
|
||||||
socketManager.handleQueryJitsiJwtMessage(
|
socketManager.handleQueryJitsiJwtMessage(
|
||||||
user,
|
user,
|
||||||
|
@ -531,15 +531,6 @@ export class SocketManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emitPlayGlobalMessage(room: GameRoom, playGlobalMessage: PlayGlobalMessage) {
|
|
||||||
const serverToClientMessage = new ServerToClientMessage();
|
|
||||||
serverToClientMessage.setPlayglobalmessage(playGlobalMessage);
|
|
||||||
|
|
||||||
for (const [id, user] of room.getUsers().entries()) {
|
|
||||||
user.socket.write(serverToClientMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public getWorlds(): Map<string, PromiseLike<GameRoom>> {
|
public getWorlds(): Map<string, PromiseLike<GameRoom>> {
|
||||||
return this.roomsPromises;
|
return this.roomsPromises;
|
||||||
}
|
}
|
||||||
|
24
docs/maps/api-camera.md
Normal file
24
docs/maps/api-camera.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{.section-title.accent.text-primary}
|
||||||
|
# API Camera functions Reference
|
||||||
|
|
||||||
|
### Listen to camera updates
|
||||||
|
|
||||||
|
```
|
||||||
|
WA.camera.onCameraUpdate(): Subscription
|
||||||
|
```
|
||||||
|
|
||||||
|
Listens to updates of the camera viewport. It will trigger for every update of the camera's properties (position or scale for instance). An event will be sent.
|
||||||
|
|
||||||
|
The event has the following attributes :
|
||||||
|
* **x (number):** coordinate X of the camera's world view (the area looked at by the camera).
|
||||||
|
* **y (number):** coordinate Y of the camera's world view.
|
||||||
|
* **width (number):** the width of the camera's world view.
|
||||||
|
* **height (number):** the height of the camera's world view.
|
||||||
|
|
||||||
|
**callback:** the function that will be called when the camera is updated.
|
||||||
|
|
||||||
|
Example :
|
||||||
|
```javascript
|
||||||
|
const subscription = WA.camera.onCameraUpdate().subscribe((worldView) => console.log(worldView));
|
||||||
|
//later...
|
||||||
|
subscription.unsubscribe();
|
@ -86,6 +86,27 @@ WA.onInit().then(() => {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Get the position of the player
|
||||||
|
```
|
||||||
|
WA.player.getPosition(): Promise<Position>
|
||||||
|
```
|
||||||
|
The player's current position is available using the `WA.player.getPosition()` function.
|
||||||
|
|
||||||
|
`Position` has the following attributes :
|
||||||
|
* **x (number) :** The coordinate x of the current player's position.
|
||||||
|
* **y (number) :** The coordinate y of the current player's position.
|
||||||
|
|
||||||
|
|
||||||
|
{.alert.alert-info}
|
||||||
|
You need to wait for the end of the initialization before calling `WA.player.getPosition()`
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
WA.onInit().then(async () => {
|
||||||
|
console.log('Position: ', await WA.player.getPosition());
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Listen to player movement
|
### Listen to player movement
|
||||||
```
|
```
|
||||||
WA.player.onPlayerMove(callback: HasPlayerMovedEventCallback): void;
|
WA.player.onPlayerMove(callback: HasPlayerMovedEventCallback): void;
|
||||||
@ -107,6 +128,30 @@ Example :
|
|||||||
WA.player.onPlayerMove(console.log);
|
WA.player.onPlayerMove(console.log);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Player specific variables
|
||||||
|
Similarly to maps (see [API state related functions](api-state.md)), it is possible to store data **related to a specific player** in a "state". Such data will be stored using the local storage from the user's browser. Any value that is serializable in JSON can be stored.
|
||||||
|
|
||||||
|
{.alert.alert-info}
|
||||||
|
In the future, player-related variables will be stored on the WorkAdventure server if the current player is logged.
|
||||||
|
|
||||||
|
Any value that is serializable in JSON can be stored.
|
||||||
|
|
||||||
|
### Setting a property
|
||||||
|
A player property can be set simply by assigning a value.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```javascript
|
||||||
|
WA.player.state.toto = "value" //will set the "toto" key to "value"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reading a variable
|
||||||
|
A player variable can be read by calling its key from the player's state.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```javascript
|
||||||
|
WA.player.state.toto //will retrieve the variable
|
||||||
|
```
|
||||||
|
|
||||||
### Set the outline color of the player
|
### Set the outline color of the player
|
||||||
```
|
```
|
||||||
WA.player.setOutlineColor(red: number, green: number, blue: number): Promise<void>;
|
WA.player.setOutlineColor(red: number, green: number, blue: number): Promise<void>;
|
||||||
|
@ -10,5 +10,6 @@
|
|||||||
- [UI functions](api-ui.md)
|
- [UI functions](api-ui.md)
|
||||||
- [Sound functions](api-sound.md)
|
- [Sound functions](api-sound.md)
|
||||||
- [Controls functions](api-controls.md)
|
- [Controls functions](api-controls.md)
|
||||||
|
- [Camera functions](api-camera.md)
|
||||||
|
|
||||||
- [List of deprecated functions](api-deprecated.md)
|
- [List of deprecated functions](api-deprecated.md)
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
{.section-title.accent.text-primary}
|
{.section-title.accent.text-primary}
|
||||||
|
|
||||||
# API Room functions Reference
|
# API Room functions Reference
|
||||||
|
|
||||||
### Working with group layers
|
### Working with group layers
|
||||||
If you use group layers in your map, to reference a layer in a group you will need to use a `/` to join layer names together.
|
|
||||||
|
If you use group layers in your map, to reference a layer in a group you will need to use a `/` to join layer names
|
||||||
|
together.
|
||||||
|
|
||||||
Example :
|
Example :
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -12,6 +15,7 @@ Example :
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
The name of the layers of this map are :
|
The name of the layers of this map are :
|
||||||
|
|
||||||
* `entries/start`
|
* `entries/start`
|
||||||
* `bottom/ground/under`
|
* `bottom/ground/under`
|
||||||
* `bottom/build/carpet`
|
* `bottom/build/carpet`
|
||||||
@ -26,29 +30,32 @@ WA.room.onLeaveLayer(name: string): Subscription
|
|||||||
|
|
||||||
Listens to the position of the current user. The event is triggered when the user enters or leaves a given layer.
|
Listens to the position of the current user. The event is triggered when the user enters or leaves a given layer.
|
||||||
|
|
||||||
* **name**: the name of the layer who as defined in Tiled.
|
* **name**: the name of the layer who as defined in Tiled.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
WA.room.onEnterLayer('myLayer').subscribe(() => {
|
WA.room.onEnterLayer('myLayer').subscribe(() => {
|
||||||
WA.chat.sendChatMessage("Hello!", 'Mr Robot');
|
WA.chat.sendChatMessage("Hello!", 'Mr Robot');
|
||||||
});
|
});
|
||||||
|
|
||||||
WA.room.onLeaveLayer('myLayer').subscribe(() => {
|
WA.room.onLeaveLayer('myLayer').subscribe(() => {
|
||||||
WA.chat.sendChatMessage("Goodbye!", 'Mr Robot');
|
WA.chat.sendChatMessage("Goodbye!", 'Mr Robot');
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### Show / Hide a layer
|
### Show / Hide a layer
|
||||||
|
|
||||||
```
|
```
|
||||||
WA.room.showLayer(layerName : string): void
|
WA.room.showLayer(layerName : string): void
|
||||||
WA.room.hideLayer(layerName : string) : void
|
WA.room.hideLayer(layerName : string) : void
|
||||||
```
|
```
|
||||||
These 2 methods can be used to show and hide a layer.
|
|
||||||
if `layerName` is the name of a group layer, show/hide all the layer in that group layer.
|
These 2 methods can be used to show and hide a layer. if `layerName` is the name of a group layer, show/hide all the
|
||||||
|
layer in that group layer.
|
||||||
|
|
||||||
Example :
|
Example :
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
WA.room.showLayer('bottom');
|
WA.room.showLayer('bottom');
|
||||||
//...
|
//...
|
||||||
@ -61,12 +68,14 @@ WA.room.hideLayer('bottom');
|
|||||||
WA.room.setProperty(layerName : string, propertyName : string, propertyValue : string | number | boolean | undefined) : void;
|
WA.room.setProperty(layerName : string, propertyName : string, propertyValue : string | number | boolean | undefined) : void;
|
||||||
```
|
```
|
||||||
|
|
||||||
Set the value of the `propertyName` property of the layer `layerName` at `propertyValue`. If the property doesn't exist, create the property `propertyName` and set the value of the property at `propertyValue`.
|
Set the value of the `propertyName` property of the layer `layerName` at `propertyValue`. If the property doesn't exist,
|
||||||
|
create the property `propertyName` and set the value of the property at `propertyValue`.
|
||||||
|
|
||||||
Note :
|
Note :
|
||||||
To unset a property from a layer, use `setProperty` with `propertyValue` set to `undefined`.
|
To unset a property from a layer, use `setProperty` with `propertyValue` set to `undefined`.
|
||||||
|
|
||||||
Example :
|
Example :
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
WA.room.setProperty('wikiLayer', 'openWebsite', 'https://www.wikipedia.org/');
|
WA.room.setProperty('wikiLayer', 'openWebsite', 'https://www.wikipedia.org/');
|
||||||
```
|
```
|
||||||
@ -79,13 +88,12 @@ WA.room.id: string;
|
|||||||
|
|
||||||
The ID of the current room is available from the `WA.room.id` property.
|
The ID of the current room is available from the `WA.room.id` property.
|
||||||
|
|
||||||
{.alert.alert-info}
|
{.alert.alert-info} You need to wait for the end of the initialization before accessing `WA.room.id`
|
||||||
You need to wait for the end of the initialization before accessing `WA.room.id`
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
WA.onInit().then(() => {
|
WA.onInit().then(() => {
|
||||||
console.log('Room id: ', WA.room.id);
|
console.log('Room id: ', WA.room.id);
|
||||||
// Will output something like: 'https://play.workadventu.re/@/myorg/myworld/myroom', or 'https://play.workadventu.re/_/global/mymap.org/map.json"
|
// Will output something like: 'https://play.workadventu.re/@/myorg/myworld/myroom', or 'https://play.workadventu.re/_/global/mymap.org/map.json"
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -97,19 +105,17 @@ WA.room.mapURL: string;
|
|||||||
|
|
||||||
The URL of the map is available from the `WA.room.mapURL` property.
|
The URL of the map is available from the `WA.room.mapURL` property.
|
||||||
|
|
||||||
{.alert.alert-info}
|
{.alert.alert-info} You need to wait for the end of the initialization before accessing `WA.room.mapURL`
|
||||||
You need to wait for the end of the initialization before accessing `WA.room.mapURL`
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
WA.onInit().then(() => {
|
WA.onInit().then(() => {
|
||||||
console.log('Map URL: ', WA.room.mapURL);
|
console.log('Map URL: ', WA.room.mapURL);
|
||||||
// Will output something like: 'https://mymap.org/map.json"
|
// Will output something like: 'https://mymap.org/map.json"
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Getting map data
|
### Getting map data
|
||||||
|
|
||||||
```
|
```
|
||||||
WA.room.getTiledMap(): Promise<ITiledMap>
|
WA.room.getTiledMap(): Promise<ITiledMap>
|
||||||
```
|
```
|
||||||
@ -121,12 +127,16 @@ const map = await WA.room.getTiledMap();
|
|||||||
console.log("Map generated with Tiled version ", map.tiledversion);
|
console.log("Map generated with Tiled version ", map.tiledversion);
|
||||||
```
|
```
|
||||||
|
|
||||||
Check the [Tiled documentation to learn more about the format of the JSON map](https://doc.mapeditor.org/en/stable/reference/json-map-format/).
|
Check
|
||||||
|
the [Tiled documentation to learn more about the format of the JSON map](https://doc.mapeditor.org/en/stable/reference/json-map-format/)
|
||||||
|
.
|
||||||
|
|
||||||
### Changing tiles
|
### Changing tiles
|
||||||
|
|
||||||
```
|
```
|
||||||
WA.room.setTiles(tiles: TileDescriptor[]): void
|
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`.
|
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`.
|
If `tile` is a string, it's not the id of the tile but the value of the property `name`.
|
||||||
@ -137,43 +147,48 @@ If `tile` is a string, it's not the id of the tile but the value of the property
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
`TileDescriptor` has the following attributes :
|
`TileDescriptor` has the following attributes :
|
||||||
|
|
||||||
* **x (number) :** The coordinate x of the tile that you want to replace.
|
* **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.
|
* **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.
|
* **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.
|
* **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.
|
**Important !** : If you use `tile` as a number, be sure to add the `firstgid` of the tileset of the tile that you want
|
||||||
|
to the id of the tile in Tiled Editor.
|
||||||
|
|
||||||
Note: If you want to unset a tile, use `setTiles` with `tile` set to `null`.
|
Note: If you want to unset a tile, use `setTiles` with `tile` set to `null`.
|
||||||
|
|
||||||
Example :
|
Example :
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
WA.room.setTiles([
|
WA.room.setTiles([
|
||||||
{x: 6, y: 4, tile: 'blue', layer: 'setTiles'},
|
{ x: 6, y: 4, tile: 'blue', layer: 'setTiles' },
|
||||||
{x: 7, y: 4, tile: 109, layer: 'setTiles'},
|
{ x: 7, y: 4, tile: 109, layer: 'setTiles' },
|
||||||
{x: 8, y: 4, tile: 109, layer: 'setTiles'},
|
{ x: 8, y: 4, tile: 109, layer: 'setTiles' },
|
||||||
{x: 9, y: 4, tile: 'blue', layer: 'setTiles'}
|
{ x: 9, y: 4, tile: 'blue', layer: 'setTiles' }
|
||||||
]);
|
]);
|
||||||
```
|
```
|
||||||
|
|
||||||
### Loading a tileset
|
### Loading a tileset
|
||||||
|
|
||||||
```
|
```
|
||||||
WA.room.loadTileset(url: string): Promise<number>
|
WA.room.loadTileset(url: string): Promise<number>
|
||||||
```
|
```
|
||||||
|
|
||||||
Load a tileset in JSON format from an url and return the id of the first tile of the loaded tileset.
|
Load a tileset in JSON format from an url and return the id of the first tile of the loaded tileset.
|
||||||
|
|
||||||
You can create a tileset file in Tile Editor.
|
You can create a tileset file in Tile Editor.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
WA.room.loadTileset("Assets/Tileset.json").then((firstId) => {
|
WA.room.loadTileset("Assets/Tileset.json").then((firstId) => {
|
||||||
WA.room.setTiles([{x: 4, y: 4, tile: firstId, layer: 'bottom'}]);
|
WA.room.setTiles([{ x: 4, y: 4, tile: firstId, layer: 'bottom' }]);
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Embedding websites in a map
|
## Embedding websites in a map
|
||||||
|
|
||||||
You can use the scripting API to embed websites in a map, or to edit websites that are already embedded (using the ["website" objects](website-in-map.md)).
|
You can use the scripting API to embed websites in a map, or to edit websites that are already embedded (using
|
||||||
|
the ["website" objects](website-in-map.md)).
|
||||||
|
|
||||||
### Getting an instance of a website already embedded in the map
|
### Getting an instance of a website already embedded in the map
|
||||||
|
|
||||||
@ -181,8 +196,8 @@ You can use the scripting API to embed websites in a map, or to edit websites th
|
|||||||
WA.room.website.get(objectName: string): Promise<EmbeddedWebsite>
|
WA.room.website.get(objectName: string): Promise<EmbeddedWebsite>
|
||||||
```
|
```
|
||||||
|
|
||||||
You can get an instance of an embedded website by using the `WA.room.website.get()` method.
|
You can get an instance of an embedded website by using the `WA.room.website.get()` method. It returns a promise of
|
||||||
It returns a promise of an `EmbeddedWebsite` instance.
|
an `EmbeddedWebsite` instance.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Get an existing website object where 'my_website' is the name of the object (on any layer object of the map)
|
// Get an existing website object where 'my_website' is the name of the object (on any layer object of the map)
|
||||||
@ -191,7 +206,6 @@ website.url = 'https://example.com';
|
|||||||
website.visible = true;
|
website.visible = true;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Adding a new website in a map
|
### Adding a new website in a map
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -201,34 +215,38 @@ interface CreateEmbeddedWebsiteEvent {
|
|||||||
name: string; // A unique name for this iframe
|
name: string; // A unique name for this iframe
|
||||||
url: string; // The URL the iframe points to.
|
url: string; // The URL the iframe points to.
|
||||||
position: {
|
position: {
|
||||||
x: number, // In pixels, relative to the map coordinates
|
x: number, // In "game" pixels, relative to the map or player coordinates, depending on origin
|
||||||
y: number, // In pixels, relative to the map coordinates
|
y: number, // In "game" pixels, relative to the map or player coordinates, depending on origin
|
||||||
width: number, // In pixels, sensitive to zoom level
|
width: number, // In "game" pixels
|
||||||
height: number, // In pixels, sensitive to zoom level
|
height: number, // In "game" pixels
|
||||||
},
|
},
|
||||||
visible?: boolean, // Whether to display the iframe or not
|
visible?: boolean, // Whether to display the iframe or not
|
||||||
allowApi?: boolean, // Whether the scripting API should be available to the iframe
|
allowApi?: boolean, // Whether the scripting API should be available to the iframe
|
||||||
allow?: string, // The list of feature policies allowed
|
allow?: string, // The list of feature policies allowed
|
||||||
|
origin: "player" | "map" // The origin used to place the x and y coordinates of the iframe's top-left corner, defaults to "map"
|
||||||
|
scale: number, // A ratio used to resize the iframe
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
You can create an instance of an embedded website by using the `WA.room.website.create()` method.
|
You can create an instance of an embedded website by using the `WA.room.website.create()` method. It returns
|
||||||
It returns an `EmbeddedWebsite` instance.
|
an `EmbeddedWebsite` instance.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Create a new website object
|
// Create a new website object
|
||||||
const website = WA.room.website.create({
|
const website = WA.room.website.create({
|
||||||
name: "my_website",
|
name: "my_website",
|
||||||
url: "https://example.com",
|
url: "https://example.com",
|
||||||
position: {
|
position: {
|
||||||
x: 64,
|
x: 64,
|
||||||
y: 128,
|
y: 128,
|
||||||
width: 320,
|
width: 320,
|
||||||
height: 240,
|
height: 240,
|
||||||
},
|
},
|
||||||
visible: true,
|
visible: true,
|
||||||
allowApi: true,
|
allowApi: true,
|
||||||
allow: "fullscreen",
|
allow: "fullscreen",
|
||||||
|
origin: "map",
|
||||||
|
scale: 1,
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -240,30 +258,28 @@ WA.room.website.delete(name: string): Promise<void>
|
|||||||
|
|
||||||
Use `WA.room.website.delete` to completely remove an embedded website from your map.
|
Use `WA.room.website.delete` to completely remove an embedded website from your map.
|
||||||
|
|
||||||
|
|
||||||
### The EmbeddedWebsite class
|
### The EmbeddedWebsite class
|
||||||
|
|
||||||
Instances of the `EmbeddedWebsite` class represent the website displayed on the map.
|
Instances of the `EmbeddedWebsite` class represent the website displayed on the map.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class EmbeddedWebsite {
|
class EmbeddedWebsite {
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
url: string;
|
url: string;
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
allow: string;
|
allow: string;
|
||||||
allowApi: boolean;
|
allowApi: boolean;
|
||||||
x: number; // In pixels, relative to the map coordinates
|
x: number; // In "game" pixels, relative to the map or player coordinates, depending on origin
|
||||||
y: number; // In pixels, relative to the map coordinates
|
y: number; // In "game" pixels, relative to the map or player coordinates, depending on origin
|
||||||
width: number; // In pixels, sensitive to zoom level
|
width: number; // In "game" pixels
|
||||||
height: number; // In pixels, sensitive to zoom level
|
height: number; // In "game" pixels
|
||||||
|
origin: "player" | "map";
|
||||||
|
scale: number;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
When you modify a property of an `EmbeddedWebsite` instance, the iframe is automatically modified in the map.
|
When you modify a property of an `EmbeddedWebsite` instance, the iframe is automatically modified in the map.
|
||||||
|
|
||||||
|
{.alert.alert-warning} The websites you add/edit/delete via the scripting API are only shown locally. If you want them
|
||||||
{.alert.alert-warning}
|
to be displayed for every player, you can use [variables](api-start.md) to share a common state between all users.
|
||||||
The websites you add/edit/delete via the scripting API are only shown locally. If you want them
|
|
||||||
to be displayed for every player, you can use [variables](api-start.md) to share a common state
|
|
||||||
between all users.
|
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@ module.exports = {
|
|||||||
"no-unused-vars": "off",
|
"no-unused-vars": "off",
|
||||||
"@typescript-eslint/no-explicit-any": "error",
|
"@typescript-eslint/no-explicit-any": "error",
|
||||||
// TODO: remove those ignored rules and write a stronger code!
|
// TODO: remove those ignored rules and write a stronger code!
|
||||||
"@typescript-eslint/no-floating-promises": "off",
|
|
||||||
"@typescript-eslint/no-unsafe-call": "off",
|
"@typescript-eslint/no-unsafe-call": "off",
|
||||||
"@typescript-eslint/restrict-plus-operands": "off",
|
"@typescript-eslint/restrict-plus-operands": "off",
|
||||||
"@typescript-eslint/no-unsafe-assignment": "off",
|
"@typescript-eslint/no-unsafe-assignment": "off",
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
FROM node:14.15.4-buster-slim@sha256:cbae886186467bbfd274b82a234a1cdfbbd31201c2a6ee63a6893eefcf3c6e76 as builder
|
FROM node:14.15.4-buster-slim@sha256:cbae886186467bbfd274b82a234a1cdfbbd31201c2a6ee63a6893eefcf3c6e76 as builder
|
||||||
WORKDIR /usr/src
|
WORKDIR /usr/src
|
||||||
COPY messages .
|
COPY messages .
|
||||||
RUN yarn install && yarn proto
|
RUN yarn install && yarn ts-proto
|
||||||
|
|
||||||
# we are rebuilding on each deploy to cope with the PUSHER_URL environment URL
|
# we are rebuilding on each deploy to cope with the PUSHER_URL environment URL
|
||||||
FROM thecodingmachine/nodejs:14-apache
|
FROM thecodingmachine/nodejs:14-apache
|
||||||
|
|
||||||
COPY --chown=docker:docker front .
|
COPY --chown=docker:docker front .
|
||||||
COPY --from=builder --chown=docker:docker /usr/src/generated /var/www/html/src/Messages/generated
|
COPY --from=builder --chown=docker:docker /usr/src/ts-proto-generated/protos /var/www/html/src/Messages/ts-proto-generated
|
||||||
|
RUN sed -i 's/import { Observable } from "rxjs";/import type { Observable } from "rxjs";/g' /var/www/html/src/Messages/ts-proto-generated/messages.ts
|
||||||
COPY --from=builder --chown=docker:docker /usr/src/JsonMessages /var/www/html/src/Messages/JsonMessages
|
COPY --from=builder --chown=docker:docker /usr/src/JsonMessages /var/www/html/src/Messages/JsonMessages
|
||||||
|
|
||||||
# Removing the iframe.html file from the final image as this adds a XSS attack.
|
# Removing the iframe.html file from the final image as this adds a XSS attack.
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
"simple-peer": "^9.11.0",
|
"simple-peer": "^9.11.0",
|
||||||
"socket.io-client": "^2.3.0",
|
"socket.io-client": "^2.3.0",
|
||||||
"standardized-audio-context": "^25.2.4",
|
"standardized-audio-context": "^25.2.4",
|
||||||
|
"ts-proto": "^1.96.0",
|
||||||
"uuidv4": "^6.2.10"
|
"uuidv4": "^6.2.10"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -18,64 +18,84 @@ class AnalyticsClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
identifyUser(uuid: string, email: string | null) {
|
identifyUser(uuid: string, email: string | null) {
|
||||||
this.posthogPromise?.then((posthog) => {
|
this.posthogPromise
|
||||||
posthog.identify(uuid, { uuid, email, wa: true });
|
?.then((posthog) => {
|
||||||
});
|
posthog.identify(uuid, { uuid, email, wa: true });
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
loggedWithSso() {
|
loggedWithSso() {
|
||||||
this.posthogPromise?.then((posthog) => {
|
this.posthogPromise
|
||||||
posthog.capture("wa-logged-sso");
|
?.then((posthog) => {
|
||||||
});
|
posthog.capture("wa-logged-sso");
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
loggedWithToken() {
|
loggedWithToken() {
|
||||||
this.posthogPromise?.then((posthog) => {
|
this.posthogPromise
|
||||||
posthog.capture("wa-logged-token");
|
?.then((posthog) => {
|
||||||
});
|
posthog.capture("wa-logged-token");
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
enteredRoom(roomId: string, roomGroup: string | null) {
|
enteredRoom(roomId: string, roomGroup: string | null) {
|
||||||
this.posthogPromise?.then((posthog) => {
|
this.posthogPromise
|
||||||
posthog.capture("$pageView", { roomId, roomGroup });
|
?.then((posthog) => {
|
||||||
posthog.capture("enteredRoom");
|
posthog.capture("$pageView", { roomId, roomGroup });
|
||||||
});
|
posthog.capture("enteredRoom");
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
openedMenu() {
|
openedMenu() {
|
||||||
this.posthogPromise?.then((posthog) => {
|
this.posthogPromise
|
||||||
posthog.capture("wa-opened-menu");
|
?.then((posthog) => {
|
||||||
});
|
posthog.capture("wa-opened-menu");
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
launchEmote(emote: string) {
|
launchEmote(emote: string) {
|
||||||
this.posthogPromise?.then((posthog) => {
|
this.posthogPromise
|
||||||
posthog.capture("wa-emote-launch", { emote });
|
?.then((posthog) => {
|
||||||
});
|
posthog.capture("wa-emote-launch", { emote });
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
enteredJitsi(roomName: string, roomId: string) {
|
enteredJitsi(roomName: string, roomId: string) {
|
||||||
this.posthogPromise?.then((posthog) => {
|
this.posthogPromise
|
||||||
posthog.capture("wa-entered-jitsi", { roomName, roomId });
|
?.then((posthog) => {
|
||||||
});
|
posthog.capture("wa-entered-jitsi", { roomName, roomId });
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
validationName() {
|
validationName() {
|
||||||
this.posthogPromise?.then((posthog) => {
|
this.posthogPromise
|
||||||
posthog.capture("wa-name-validation");
|
?.then((posthog) => {
|
||||||
});
|
posthog.capture("wa-name-validation");
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
validationWoka(scene: string) {
|
validationWoka(scene: string) {
|
||||||
this.posthogPromise?.then((posthog) => {
|
this.posthogPromise
|
||||||
posthog.capture("wa-woka-validation", { scene });
|
?.then((posthog) => {
|
||||||
});
|
posthog.capture("wa-woka-validation", { scene });
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
validationVideo() {
|
validationVideo() {
|
||||||
this.posthogPromise?.then((posthog) => {
|
this.posthogPromise
|
||||||
posthog.capture("wa-video-validation");
|
?.then((posthog) => {
|
||||||
});
|
posthog.capture("wa-video-validation");
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const analyticsClient = new AnalyticsClient();
|
export const analyticsClient = new AnalyticsClient();
|
||||||
|
@ -22,6 +22,8 @@ export const isEmbeddedWebsiteEvent = new tg.IsInterface()
|
|||||||
y: tg.isNumber,
|
y: tg.isNumber,
|
||||||
width: tg.isNumber,
|
width: tg.isNumber,
|
||||||
height: tg.isNumber,
|
height: tg.isNumber,
|
||||||
|
origin: tg.isSingletonStringUnion("player", "map"),
|
||||||
|
scale: tg.isNumber,
|
||||||
})
|
})
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
@ -35,6 +37,8 @@ export const isCreateEmbeddedWebsiteEvent = new tg.IsInterface()
|
|||||||
visible: tg.isBoolean,
|
visible: tg.isBoolean,
|
||||||
allowApi: tg.isBoolean,
|
allowApi: tg.isBoolean,
|
||||||
allow: tg.isString,
|
allow: tg.isString,
|
||||||
|
origin: tg.isSingletonStringUnion("player", "map"),
|
||||||
|
scale: tg.isNumber,
|
||||||
})
|
})
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ export const isGameStateEvent = new tg.IsInterface()
|
|||||||
tags: tg.isArray(tg.isString),
|
tags: tg.isArray(tg.isString),
|
||||||
variables: tg.isObject,
|
variables: tg.isObject,
|
||||||
userRoomToken: tg.isUnion(tg.isString, tg.isUndefined),
|
userRoomToken: tg.isUnion(tg.isString, tg.isUndefined),
|
||||||
|
playerVariables: tg.isObject,
|
||||||
})
|
})
|
||||||
.get();
|
.get();
|
||||||
/**
|
/**
|
||||||
|
@ -30,6 +30,8 @@ import type { MenuRegisterEvent, UnregisterMenuEvent } from "./ui/MenuRegisterEv
|
|||||||
import type { ChangeLayerEvent } from "./ChangeLayerEvent";
|
import type { ChangeLayerEvent } from "./ChangeLayerEvent";
|
||||||
import type { ChangeZoneEvent } from "./ChangeZoneEvent";
|
import type { ChangeZoneEvent } from "./ChangeZoneEvent";
|
||||||
import { isColorEvent } from "./ColorEvent";
|
import { isColorEvent } from "./ColorEvent";
|
||||||
|
import { isPlayerPosition } from "./PlayerPosition";
|
||||||
|
import type { WasCameraUpdatedEvent } from "./WasCameraUpdatedEvent";
|
||||||
|
|
||||||
export interface TypedMessageEvent<T> extends MessageEvent {
|
export interface TypedMessageEvent<T> extends MessageEvent {
|
||||||
data: T;
|
data: T;
|
||||||
@ -50,6 +52,7 @@ export type IframeEventMap = {
|
|||||||
displayBubble: null;
|
displayBubble: null;
|
||||||
removeBubble: null;
|
removeBubble: null;
|
||||||
onPlayerMove: undefined;
|
onPlayerMove: undefined;
|
||||||
|
onCameraUpdate: undefined;
|
||||||
showLayer: LayerEvent;
|
showLayer: LayerEvent;
|
||||||
hideLayer: LayerEvent;
|
hideLayer: LayerEvent;
|
||||||
setProperty: SetPropertyEvent;
|
setProperty: SetPropertyEvent;
|
||||||
@ -82,6 +85,7 @@ export interface IframeResponseEventMap {
|
|||||||
leaveZoneEvent: ChangeZoneEvent;
|
leaveZoneEvent: ChangeZoneEvent;
|
||||||
buttonClickedEvent: ButtonClickedEvent;
|
buttonClickedEvent: ButtonClickedEvent;
|
||||||
hasPlayerMoved: HasPlayerMovedEvent;
|
hasPlayerMoved: HasPlayerMovedEvent;
|
||||||
|
wasCameraUpdated: WasCameraUpdatedEvent;
|
||||||
menuItemClicked: MenuItemClickedEvent;
|
menuItemClicked: MenuItemClickedEvent;
|
||||||
setVariable: SetVariableEvent;
|
setVariable: SetVariableEvent;
|
||||||
messageTriggered: MessageReferenceEvent;
|
messageTriggered: MessageReferenceEvent;
|
||||||
@ -161,6 +165,10 @@ export const iframeQueryMapTypeGuards = {
|
|||||||
query: tg.isUndefined,
|
query: tg.isUndefined,
|
||||||
answer: tg.isUndefined,
|
answer: tg.isUndefined,
|
||||||
},
|
},
|
||||||
|
getPlayerPosition: {
|
||||||
|
query: tg.isUndefined,
|
||||||
|
answer: isPlayerPosition,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
type GuardedType<T> = T extends (x: unknown) => x is infer T ? T : never;
|
type GuardedType<T> = T extends (x: unknown) => x is infer T ? T : never;
|
||||||
|
10
front/src/Api/Events/PlayerPosition.ts
Normal file
10
front/src/Api/Events/PlayerPosition.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import * as tg from "generic-type-guard";
|
||||||
|
|
||||||
|
export const isPlayerPosition = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
x: tg.isNumber,
|
||||||
|
y: tg.isNumber,
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
|
||||||
|
export type PlayerPosition = tg.GuardedType<typeof isPlayerPosition>;
|
@ -4,6 +4,7 @@ export const isSetVariableEvent = new tg.IsInterface()
|
|||||||
.withProperties({
|
.withProperties({
|
||||||
key: tg.isString,
|
key: tg.isString,
|
||||||
value: tg.isUnknown,
|
value: tg.isUnknown,
|
||||||
|
target: tg.isSingletonStringUnion("global", "player"),
|
||||||
})
|
})
|
||||||
.get();
|
.get();
|
||||||
/**
|
/**
|
||||||
|
19
front/src/Api/Events/WasCameraUpdatedEvent.ts
Normal file
19
front/src/Api/Events/WasCameraUpdatedEvent.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import * as tg from "generic-type-guard";
|
||||||
|
|
||||||
|
export const isWasCameraUpdatedEvent = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
x: tg.isNumber,
|
||||||
|
y: tg.isNumber,
|
||||||
|
width: tg.isNumber,
|
||||||
|
height: tg.isNumber,
|
||||||
|
zoom: tg.isNumber,
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message sent from the game to the iFrame to notify a movement from the camera.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type WasCameraUpdatedEvent = tg.GuardedType<typeof isWasCameraUpdatedEvent>;
|
||||||
|
|
||||||
|
export type WasCameraUpdatedEventCallback = (event: WasCameraUpdatedEvent) => void;
|
@ -31,6 +31,7 @@ import type { SetVariableEvent } from "./Events/SetVariableEvent";
|
|||||||
import { ModifyEmbeddedWebsiteEvent, isEmbeddedWebsiteEvent } from "./Events/EmbeddedWebsiteEvent";
|
import { ModifyEmbeddedWebsiteEvent, isEmbeddedWebsiteEvent } from "./Events/EmbeddedWebsiteEvent";
|
||||||
import { handleMenuRegistrationEvent, handleMenuUnregisterEvent } from "../Stores/MenuStore";
|
import { handleMenuRegistrationEvent, handleMenuUnregisterEvent } from "../Stores/MenuStore";
|
||||||
import type { ChangeLayerEvent } from "./Events/ChangeLayerEvent";
|
import type { ChangeLayerEvent } from "./Events/ChangeLayerEvent";
|
||||||
|
import type { WasCameraUpdatedEvent } from "./Events/WasCameraUpdatedEvent";
|
||||||
import type { ChangeZoneEvent } from "./Events/ChangeZoneEvent";
|
import type { ChangeZoneEvent } from "./Events/ChangeZoneEvent";
|
||||||
|
|
||||||
type AnswererCallback<T extends keyof IframeQueryMap> = (
|
type AnswererCallback<T extends keyof IframeQueryMap> = (
|
||||||
@ -85,6 +86,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 _trackCameraUpdateStream: Subject<LoadSoundEvent> = new Subject();
|
||||||
|
public readonly trackCameraUpdateStream = this._trackCameraUpdateStream.asObservable();
|
||||||
|
|
||||||
private readonly _setTilesStream: Subject<SetTilesEvent> = new Subject();
|
private readonly _setTilesStream: Subject<SetTilesEvent> = new Subject();
|
||||||
public readonly setTilesStream = this._setTilesStream.asObservable();
|
public readonly setTilesStream = this._setTilesStream.asObservable();
|
||||||
|
|
||||||
@ -226,6 +230,8 @@ class IframeListener {
|
|||||||
this._removeBubbleStream.next();
|
this._removeBubbleStream.next();
|
||||||
} else if (payload.type == "onPlayerMove") {
|
} else if (payload.type == "onPlayerMove") {
|
||||||
this.sendPlayerMove = true;
|
this.sendPlayerMove = true;
|
||||||
|
} else if (payload.type == "onCameraUpdate") {
|
||||||
|
this._trackCameraUpdateStream.next();
|
||||||
} else if (payload.type == "setTiles" && isSetTilesEvent(payload.data)) {
|
} else if (payload.type == "setTiles" && isSetTilesEvent(payload.data)) {
|
||||||
this._setTilesStream.next(payload.data);
|
this._setTilesStream.next(payload.data);
|
||||||
} else if (payload.type == "modifyEmbeddedWebsite" && isEmbeddedWebsiteEvent(payload.data)) {
|
} else if (payload.type == "modifyEmbeddedWebsite" && isEmbeddedWebsiteEvent(payload.data)) {
|
||||||
@ -442,6 +448,13 @@ class IframeListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendCameraUpdated(event: WasCameraUpdatedEvent) {
|
||||||
|
this.postMessage({
|
||||||
|
type: "wasCameraUpdated",
|
||||||
|
data: event,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
sendButtonClickedEvent(popupId: number, buttonId: number): void {
|
sendButtonClickedEvent(popupId: number, buttonId: number): void {
|
||||||
this.postMessage({
|
this.postMessage({
|
||||||
type: "buttonClickedEvent",
|
type: "buttonClickedEvent",
|
||||||
|
@ -12,6 +12,8 @@ export class EmbeddedWebsite {
|
|||||||
private _allow: string;
|
private _allow: string;
|
||||||
private _allowApi: boolean;
|
private _allowApi: boolean;
|
||||||
private _position: Rectangle;
|
private _position: Rectangle;
|
||||||
|
private readonly origin: "map" | "player" | undefined;
|
||||||
|
private _scale: number;
|
||||||
|
|
||||||
constructor(private config: CreateEmbeddedWebsiteEvent) {
|
constructor(private config: CreateEmbeddedWebsiteEvent) {
|
||||||
this.name = config.name;
|
this.name = config.name;
|
||||||
@ -20,6 +22,12 @@ export class EmbeddedWebsite {
|
|||||||
this._allow = config.allow ?? "";
|
this._allow = config.allow ?? "";
|
||||||
this._allowApi = config.allowApi ?? false;
|
this._allowApi = config.allowApi ?? false;
|
||||||
this._position = config.position;
|
this._position = config.position;
|
||||||
|
this.origin = config.origin;
|
||||||
|
this._scale = config.scale ?? 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get url() {
|
||||||
|
return this._url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public set url(url: string) {
|
public set url(url: string) {
|
||||||
@ -33,6 +41,10 @@ export class EmbeddedWebsite {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get visible() {
|
||||||
|
return this._visible;
|
||||||
|
}
|
||||||
|
|
||||||
public set visible(visible: boolean) {
|
public set visible(visible: boolean) {
|
||||||
this._visible = visible;
|
this._visible = visible;
|
||||||
sendToWorkadventure({
|
sendToWorkadventure({
|
||||||
@ -44,6 +56,10 @@ export class EmbeddedWebsite {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get x() {
|
||||||
|
return this._position.x;
|
||||||
|
}
|
||||||
|
|
||||||
public set x(x: number) {
|
public set x(x: number) {
|
||||||
this._position.x = x;
|
this._position.x = x;
|
||||||
sendToWorkadventure({
|
sendToWorkadventure({
|
||||||
@ -55,6 +71,10 @@ export class EmbeddedWebsite {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get y() {
|
||||||
|
return this._position.y;
|
||||||
|
}
|
||||||
|
|
||||||
public set y(y: number) {
|
public set y(y: number) {
|
||||||
this._position.y = y;
|
this._position.y = y;
|
||||||
sendToWorkadventure({
|
sendToWorkadventure({
|
||||||
@ -66,6 +86,10 @@ export class EmbeddedWebsite {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get width() {
|
||||||
|
return this._position.width;
|
||||||
|
}
|
||||||
|
|
||||||
public set width(width: number) {
|
public set width(width: number) {
|
||||||
this._position.width = width;
|
this._position.width = width;
|
||||||
sendToWorkadventure({
|
sendToWorkadventure({
|
||||||
@ -77,6 +101,10 @@ export class EmbeddedWebsite {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get height() {
|
||||||
|
return this._position.height;
|
||||||
|
}
|
||||||
|
|
||||||
public set height(height: number) {
|
public set height(height: number) {
|
||||||
this._position.height = height;
|
this._position.height = height;
|
||||||
sendToWorkadventure({
|
sendToWorkadventure({
|
||||||
@ -87,4 +115,19 @@ export class EmbeddedWebsite {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get scale(): number {
|
||||||
|
return this._scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set scale(scale: number) {
|
||||||
|
this._scale = scale;
|
||||||
|
sendToWorkadventure({
|
||||||
|
type: "modifyEmbeddedWebsite",
|
||||||
|
data: {
|
||||||
|
name: this.name,
|
||||||
|
scale: this._scale,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ export class ActionMessage {
|
|||||||
this.message = actionMessageOptions.message;
|
this.message = actionMessageOptions.message;
|
||||||
this.type = actionMessageOptions.type ?? "message";
|
this.type = actionMessageOptions.type ?? "message";
|
||||||
this.callback = actionMessageOptions.callback;
|
this.callback = actionMessageOptions.callback;
|
||||||
this.create();
|
this.create().catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async create() {
|
private async create() {
|
||||||
|
29
front/src/Api/iframe/camera.ts
Normal file
29
front/src/Api/iframe/camera.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribution";
|
||||||
|
import { Subject } from "rxjs";
|
||||||
|
import type { WasCameraUpdatedEvent } from "../Events/WasCameraUpdatedEvent";
|
||||||
|
import { apiCallback } from "./registeredCallbacks";
|
||||||
|
import { isWasCameraUpdatedEvent } from "../Events/WasCameraUpdatedEvent";
|
||||||
|
|
||||||
|
const moveStream = new Subject<WasCameraUpdatedEvent>();
|
||||||
|
|
||||||
|
export class WorkAdventureCameraCommands extends IframeApiContribution<WorkAdventureCameraCommands> {
|
||||||
|
callbacks = [
|
||||||
|
apiCallback({
|
||||||
|
type: "wasCameraUpdated",
|
||||||
|
typeChecker: isWasCameraUpdatedEvent,
|
||||||
|
callback: (payloadData) => {
|
||||||
|
moveStream.next(payloadData);
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
onCameraUpdate(): Subject<WasCameraUpdatedEvent> {
|
||||||
|
sendToWorkadventure({
|
||||||
|
type: "onCameraUpdate",
|
||||||
|
data: null,
|
||||||
|
});
|
||||||
|
return moveStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new WorkAdventureCameraCommands();
|
@ -3,6 +3,7 @@ import type { HasPlayerMovedEvent, HasPlayerMovedEventCallback } from "../Events
|
|||||||
import { Subject } from "rxjs";
|
import { Subject } from "rxjs";
|
||||||
import { apiCallback } from "./registeredCallbacks";
|
import { apiCallback } from "./registeredCallbacks";
|
||||||
import { isHasPlayerMovedEvent } from "../Events/HasPlayerMovedEvent";
|
import { isHasPlayerMovedEvent } from "../Events/HasPlayerMovedEvent";
|
||||||
|
import { createState } from "./state";
|
||||||
|
|
||||||
const moveStream = new Subject<HasPlayerMovedEvent>();
|
const moveStream = new Subject<HasPlayerMovedEvent>();
|
||||||
|
|
||||||
@ -31,6 +32,8 @@ export const setUuid = (_uuid: string | undefined) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class WorkadventurePlayerCommands extends IframeApiContribution<WorkadventurePlayerCommands> {
|
export class WorkadventurePlayerCommands extends IframeApiContribution<WorkadventurePlayerCommands> {
|
||||||
|
readonly state = createState("player");
|
||||||
|
|
||||||
callbacks = [
|
callbacks = [
|
||||||
apiCallback({
|
apiCallback({
|
||||||
type: "hasPlayerMoved",
|
type: "hasPlayerMoved",
|
||||||
@ -74,6 +77,13 @@ export class WorkadventurePlayerCommands extends IframeApiContribution<Workadven
|
|||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getPosition(): Promise<Position> {
|
||||||
|
return await queryWorkadventure({
|
||||||
|
type: "getPlayerPosition",
|
||||||
|
data: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
get userRoomToken(): string | undefined {
|
get userRoomToken(): string | undefined {
|
||||||
if (userRoomToken === undefined) {
|
if (userRoomToken === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@ -102,4 +112,9 @@ export class WorkadventurePlayerCommands extends IframeApiContribution<Workadven
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Position = {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
};
|
||||||
|
|
||||||
export default new WorkadventurePlayerCommands();
|
export default new WorkadventurePlayerCommands();
|
||||||
|
@ -8,93 +8,101 @@ import { isSetVariableEvent, SetVariableEvent } from "../Events/SetVariableEvent
|
|||||||
|
|
||||||
import type { ITiledMap } from "../../Phaser/Map/ITiledMap";
|
import type { ITiledMap } from "../../Phaser/Map/ITiledMap";
|
||||||
|
|
||||||
const setVariableResolvers = new Subject<SetVariableEvent>();
|
|
||||||
const variables = new Map<string, unknown>();
|
|
||||||
const variableSubscribers = new Map<string, Subject<unknown>>();
|
|
||||||
|
|
||||||
export const initVariables = (_variables: Map<string, unknown>): void => {
|
|
||||||
for (const [name, value] of _variables.entries()) {
|
|
||||||
// In case the user already decided to put values in the variables (before onInit), let's make sure onInit does not override this.
|
|
||||||
if (!variables.has(name)) {
|
|
||||||
variables.set(name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
setVariableResolvers.subscribe((event) => {
|
|
||||||
const oldValue = variables.get(event.key);
|
|
||||||
// If we are setting the same value, no need to do anything.
|
|
||||||
// No need to do this check since it is already performed in SharedVariablesManager
|
|
||||||
/*if (JSON.stringify(oldValue) === JSON.stringify(event.value)) {
|
|
||||||
return;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
variables.set(event.key, event.value);
|
|
||||||
const subject = variableSubscribers.get(event.key);
|
|
||||||
if (subject !== undefined) {
|
|
||||||
subject.next(event.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export class WorkadventureStateCommands extends IframeApiContribution<WorkadventureStateCommands> {
|
export class WorkadventureStateCommands extends IframeApiContribution<WorkadventureStateCommands> {
|
||||||
|
private setVariableResolvers = new Subject<SetVariableEvent>();
|
||||||
|
private variables = new Map<string, unknown>();
|
||||||
|
private variableSubscribers = new Map<string, Subject<unknown>>();
|
||||||
|
|
||||||
|
constructor(private target: "global" | "player") {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.setVariableResolvers.subscribe((event) => {
|
||||||
|
const oldValue = this.variables.get(event.key);
|
||||||
|
// If we are setting the same value, no need to do anything.
|
||||||
|
// No need to do this check since it is already performed in SharedVariablesManager
|
||||||
|
/*if (JSON.stringify(oldValue) === JSON.stringify(event.value)) {
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
this.variables.set(event.key, event.value);
|
||||||
|
const subject = this.variableSubscribers.get(event.key);
|
||||||
|
if (subject !== undefined) {
|
||||||
|
subject.next(event.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
callbacks = [
|
callbacks = [
|
||||||
apiCallback({
|
apiCallback({
|
||||||
type: "setVariable",
|
type: "setVariable",
|
||||||
typeChecker: isSetVariableEvent,
|
typeChecker: isSetVariableEvent,
|
||||||
callback: (payloadData) => {
|
callback: (payloadData) => {
|
||||||
setVariableResolvers.next(payloadData);
|
if (payloadData.target === this.target) {
|
||||||
|
this.setVariableResolvers.next(payloadData);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// TODO: see how we can remove this method from types exposed to WA.state object
|
||||||
|
initVariables(_variables: Map<string, unknown>): void {
|
||||||
|
for (const [name, value] of _variables.entries()) {
|
||||||
|
// In case the user already decided to put values in the variables (before onInit), let's make sure onInit does not override this.
|
||||||
|
if (!this.variables.has(name)) {
|
||||||
|
this.variables.set(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
saveVariable(key: string, value: unknown): Promise<void> {
|
saveVariable(key: string, value: unknown): Promise<void> {
|
||||||
variables.set(key, value);
|
this.variables.set(key, value);
|
||||||
return queryWorkadventure({
|
return queryWorkadventure({
|
||||||
type: "setVariable",
|
type: "setVariable",
|
||||||
data: {
|
data: {
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
|
target: this.target,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
loadVariable(key: string): unknown {
|
loadVariable(key: string): unknown {
|
||||||
return variables.get(key);
|
return this.variables.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
hasVariable(key: string): boolean {
|
hasVariable(key: string): boolean {
|
||||||
return variables.has(key);
|
return this.variables.has(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
onVariableChange(key: string): Observable<unknown> {
|
onVariableChange(key: string): Observable<unknown> {
|
||||||
let subject = variableSubscribers.get(key);
|
let subject = this.variableSubscribers.get(key);
|
||||||
if (subject === undefined) {
|
if (subject === undefined) {
|
||||||
subject = new Subject<unknown>();
|
subject = new Subject<unknown>();
|
||||||
variableSubscribers.set(key, subject);
|
this.variableSubscribers.set(key, subject);
|
||||||
}
|
}
|
||||||
return subject.asObservable();
|
return subject.asObservable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const proxyCommand = new Proxy(new WorkadventureStateCommands(), {
|
export function createState(target: "global" | "player"): WorkadventureStateCommands & { [key: string]: unknown } {
|
||||||
get(target: WorkadventureStateCommands, p: PropertyKey, receiver: unknown): unknown {
|
return new Proxy(new WorkadventureStateCommands(target), {
|
||||||
if (p in target) {
|
get(target: WorkadventureStateCommands, p: PropertyKey, receiver: unknown): unknown {
|
||||||
return Reflect.get(target, p, receiver);
|
if (p in target) {
|
||||||
}
|
return Reflect.get(target, p, receiver);
|
||||||
return target.loadVariable(p.toString());
|
}
|
||||||
},
|
return target.loadVariable(p.toString());
|
||||||
set(target: WorkadventureStateCommands, p: PropertyKey, value: unknown, receiver: unknown): boolean {
|
},
|
||||||
// Note: when using "set", there is no way to wait, so we ignore the return of the promise.
|
set(target: WorkadventureStateCommands, p: PropertyKey, value: unknown, receiver: unknown): boolean {
|
||||||
// User must use WA.state.saveVariable to have error message.
|
// Note: when using "set", there is no way to wait, so we ignore the return of the promise.
|
||||||
target.saveVariable(p.toString(), value);
|
// User must use WA.state.saveVariable to have error message.
|
||||||
return true;
|
target.saveVariable(p.toString(), value).catch((e) => console.error(e));
|
||||||
},
|
|
||||||
has(target: WorkadventureStateCommands, p: PropertyKey): boolean {
|
|
||||||
if (p in target) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
return target.hasVariable(p.toString());
|
has(target: WorkadventureStateCommands, p: PropertyKey): boolean {
|
||||||
},
|
if (p in target) {
|
||||||
}) as WorkadventureStateCommands & { [key: string]: unknown };
|
return true;
|
||||||
|
}
|
||||||
export default proxyCommand;
|
return target.hasVariable(p.toString());
|
||||||
|
},
|
||||||
|
}) as WorkadventureStateCommands & { [key: string]: unknown };
|
||||||
|
}
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
import type { LoadSoundEvent } from "../Events/LoadSoundEvent";
|
|
||||||
import type { PlaySoundEvent } from "../Events/PlaySoundEvent";
|
|
||||||
import type { StopSoundEvent } from "../Events/StopSoundEvent";
|
|
||||||
import { IframeApiContribution, queryWorkadventure, sendToWorkadventure } from "./IframeApiContribution";
|
import { IframeApiContribution, queryWorkadventure, sendToWorkadventure } from "./IframeApiContribution";
|
||||||
import { Sound } from "./Sound/Sound";
|
|
||||||
import { EmbeddedWebsite } from "./Room/EmbeddedWebsite";
|
import { EmbeddedWebsite } from "./Room/EmbeddedWebsite";
|
||||||
import type { CreateEmbeddedWebsiteEvent } from "../Events/EmbeddedWebsiteEvent";
|
import type { CreateEmbeddedWebsiteEvent } from "../Events/EmbeddedWebsiteEvent";
|
||||||
|
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
import { chatVisibilityStore } from "../Stores/ChatStore";
|
import { chatVisibilityStore } from "../Stores/ChatStore";
|
||||||
import { helpCameraSettingsVisibleStore } from "../Stores/HelpCameraSettingsStore";
|
import { helpCameraSettingsVisibleStore } from "../Stores/HelpCameraSettingsStore";
|
||||||
import HelpCameraSettingsPopup from "./HelpCameraSettings/HelpCameraSettingsPopup.svelte";
|
import HelpCameraSettingsPopup from "./HelpCameraSettings/HelpCameraSettingsPopup.svelte";
|
||||||
|
import { showLimitRoomModalStore, showShareLinkMapModalStore } from "../Stores/ModalStore";
|
||||||
|
import LimitRoomModal from "./Modal/LimitRoomModal.svelte";
|
||||||
|
import ShareLinkMapModal from "./Modal/ShareLinkMapModal.svelte";
|
||||||
import AudioPlaying from "./UI/AudioPlaying.svelte";
|
import AudioPlaying from "./UI/AudioPlaying.svelte";
|
||||||
import { soundPlayingStore } from "../Stores/SoundPlayingStore";
|
import { soundPlayingStore } from "../Stores/SoundPlayingStore";
|
||||||
import ErrorDialog from "./UI/ErrorDialog.svelte";
|
import ErrorDialog from "./UI/ErrorDialog.svelte";
|
||||||
@ -136,6 +139,16 @@
|
|||||||
<HelpCameraSettingsPopup />
|
<HelpCameraSettingsPopup />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if $showLimitRoomModalStore}
|
||||||
|
<div>
|
||||||
|
<LimitRoomModal />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{#if $showShareLinkMapModalStore}
|
||||||
|
<div>
|
||||||
|
<ShareLinkMapModal />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
{#if $requestVisitCardsStore}
|
{#if $requestVisitCardsStore}
|
||||||
<VisitCard visitCardUrl={$requestVisitCardsStore} />
|
<VisitCard visitCardUrl={$requestVisitCardsStore} />
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -19,12 +19,13 @@
|
|||||||
audioManagerVolumeStore.setVolume(volume);
|
audioManagerVolumeStore.setVolume(volume);
|
||||||
audioManagerVolumeStore.setMuted(localUserStore.getAudioPlayerMuted());
|
audioManagerVolumeStore.setMuted(localUserStore.getAudioPlayerMuted());
|
||||||
|
|
||||||
unsubscriberFileStore = audioManagerFileStore.subscribe(() => {
|
unsubscriberFileStore = audioManagerFileStore.subscribe((src) => {
|
||||||
HTMLAudioPlayer.pause();
|
HTMLAudioPlayer.pause();
|
||||||
|
HTMLAudioPlayer.src = src;
|
||||||
HTMLAudioPlayer.loop = get(audioManagerVolumeStore).loop;
|
HTMLAudioPlayer.loop = get(audioManagerVolumeStore).loop;
|
||||||
HTMLAudioPlayer.volume = get(audioManagerVolumeStore).volume;
|
HTMLAudioPlayer.volume = get(audioManagerVolumeStore).volume;
|
||||||
HTMLAudioPlayer.muted = get(audioManagerVolumeStore).muted;
|
HTMLAudioPlayer.muted = get(audioManagerVolumeStore).muted;
|
||||||
HTMLAudioPlayer.play();
|
void HTMLAudioPlayer.play();
|
||||||
});
|
});
|
||||||
unsubscriberVolumeStore = audioManagerVolumeStore.subscribe((audioManager: audioManagerVolume) => {
|
unsubscriberVolumeStore = audioManagerVolumeStore.subscribe((audioManager: audioManagerVolume) => {
|
||||||
const reduceVolume = audioManager.talking && audioManager.decreaseWhileTalking;
|
const reduceVolume = audioManager.talking && audioManager.decreaseWhileTalking;
|
||||||
@ -148,9 +149,7 @@
|
|||||||
</label>
|
</label>
|
||||||
<section class="audio-manager-file">
|
<section class="audio-manager-file">
|
||||||
<!-- svelte-ignore a11y-media-has-caption -->
|
<!-- svelte-ignore a11y-media-has-caption -->
|
||||||
<audio class="audio-manager-audioplayer" bind:this={HTMLAudioPlayer}>
|
<audio class="audio-manager-audioplayer" bind:this={HTMLAudioPlayer} />
|
||||||
<source src={$audioManagerFileStore} />
|
|
||||||
</audio>
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -67,6 +67,7 @@
|
|||||||
.messagePart {
|
.messagePart {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
user-select: text;
|
||||||
|
|
||||||
span.date {
|
span.date {
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
|
@ -14,14 +14,11 @@ vim: ft=typescript
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sendFollowRequest() {
|
function sendFollowRequest() {
|
||||||
gameScene.connection?.emitFollowRequest();
|
gameScene.CurrentPlayer.sendFollowRequest();
|
||||||
followRoleStore.set("leader");
|
|
||||||
followStateStore.set("active");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function acceptFollowRequest() {
|
function acceptFollowRequest() {
|
||||||
gameScene.CurrentPlayer.enableFollowing();
|
gameScene.CurrentPlayer.startFollowing();
|
||||||
gameScene.connection?.emitFollowConfirmation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function abortEnding() {
|
function abortEnding() {
|
||||||
@ -42,23 +39,15 @@ vim: ft=typescript
|
|||||||
|
|
||||||
<svelte:window on:keydown={onKeyDown} />
|
<svelte:window on:keydown={onKeyDown} />
|
||||||
|
|
||||||
{#if $followStateStore === "requesting"}
|
{#if $followStateStore === "requesting" && $followRoleStore === "follower"}
|
||||||
<div class="interact-menu nes-container is-rounded">
|
<div class="interact-menu nes-container is-rounded">
|
||||||
{#if $followRoleStore === "follower"}
|
<section class="interact-menu-title">
|
||||||
<section class="interact-menu-title">
|
<h2>Do you want to follow {name($followUsersStore[0])}?</h2>
|
||||||
<h2>Do you want to follow {name($followUsersStore[0])}?</h2>
|
</section>
|
||||||
</section>
|
<section class="interact-menu-action">
|
||||||
<section class="interact-menu-action">
|
<button type="button" class="nes-btn is-success" on:click|preventDefault={acceptFollowRequest}>Yes</button>
|
||||||
<button type="button" class="nes-btn is-success" on:click|preventDefault={acceptFollowRequest}
|
<button type="button" class="nes-btn is-error" on:click|preventDefault={reset}>No</button>
|
||||||
>Yes</button
|
</section>
|
||||||
>
|
|
||||||
<button type="button" class="nes-btn is-error" on:click|preventDefault={reset}>No</button>
|
|
||||||
</section>
|
|
||||||
{:else if $followRoleStore === "leader"}
|
|
||||||
<section class="interact-menu-question">
|
|
||||||
<p>Should never be displayed</p>
|
|
||||||
</section>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
@ -19,12 +19,12 @@
|
|||||||
uploadAudioActive = true;
|
uploadAudioActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function send() {
|
async function send(): Promise<void> {
|
||||||
if (inputSendTextActive) {
|
if (inputSendTextActive) {
|
||||||
handleSendText.sendTextMessage(broadcastToWorld);
|
return handleSendText.sendTextMessage(broadcastToWorld);
|
||||||
}
|
}
|
||||||
if (uploadAudioActive) {
|
if (uploadAudioActive) {
|
||||||
handleSendAudio.sendAudioMessage(broadcastToWorld);
|
return handleSendAudio.sendAudioMessage(broadcastToWorld);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -21,12 +21,12 @@
|
|||||||
<div class="guest-main">
|
<div class="guest-main">
|
||||||
<section class="container-overflow">
|
<section class="container-overflow">
|
||||||
<section class="share-url not-mobile">
|
<section class="share-url not-mobile">
|
||||||
<h3>Share the link of the room !</h3>
|
<h3>Share the link of the room!</h3>
|
||||||
<input type="text" readonly id="input-share-link" value={location.toString()} />
|
<input type="text" readonly id="input-share-link" value={location.toString()} />
|
||||||
<button type="button" class="nes-btn is-primary" on:click={copyLink}>Copy</button>
|
<button type="button" class="nes-btn is-primary" on:click={copyLink}>Copy</button>
|
||||||
</section>
|
</section>
|
||||||
<section class="is-mobile">
|
<section class="is-mobile">
|
||||||
<h3>Share the link of the room !</h3>
|
<h3>Share the link of the room!</h3>
|
||||||
<input type="hidden" readonly id="input-share-link" value={location.toString()} />
|
<input type="hidden" readonly id="input-share-link" value={location.toString()} />
|
||||||
<button type="button" class="nes-btn is-primary" on:click={shareLink}>Share</button>
|
<button type="button" class="nes-btn is-primary" on:click={shareLink}>Share</button>
|
||||||
</section>
|
</section>
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import logoTalk from "../images/logo-message-pixel.png";
|
import logoTalk from "../images/logo-message-pixel.png";
|
||||||
import logoWA from "../images/logo-WA-pixel.png";
|
import logoWA from "../images/logo-WA-pixel.png";
|
||||||
|
import logoInvite from "../images/logo-invite-pixel.png";
|
||||||
|
import logoRegister from "../images/logo-register-pixel.png";
|
||||||
import { menuVisiblilityStore } from "../../Stores/MenuStore";
|
import { menuVisiblilityStore } from "../../Stores/MenuStore";
|
||||||
import { chatVisibilityStore } from "../../Stores/ChatStore";
|
import { chatVisibilityStore } from "../../Stores/ChatStore";
|
||||||
|
import { limitMapStore } from "../../Stores/GameStore";
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
|
import { ADMIN_URL } from "../../Enum/EnvironmentVariable";
|
||||||
|
import { showShareLinkMapModalStore } from "../../Stores/ModalStore";
|
||||||
|
|
||||||
function showMenu() {
|
function showMenu() {
|
||||||
menuVisiblilityStore.set(!get(menuVisiblilityStore));
|
menuVisiblilityStore.set(!get(menuVisiblilityStore));
|
||||||
@ -11,13 +16,25 @@
|
|||||||
function showChat() {
|
function showChat() {
|
||||||
chatVisibilityStore.set(true);
|
chatVisibilityStore.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function register() {
|
||||||
|
window.open(`${ADMIN_URL}/second-step-register`, "_self");
|
||||||
|
}
|
||||||
|
function showInvite() {
|
||||||
|
showShareLinkMapModalStore.set(true);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window />
|
<svelte:window />
|
||||||
|
|
||||||
<main class="menuIcon">
|
<main class="menuIcon">
|
||||||
<img src={logoWA} alt="open menu" class="nes-pointer" on:click|preventDefault={showMenu} />
|
{#if $limitMapStore}
|
||||||
<img src={logoTalk} alt="open menu" class="nes-pointer" on:click|preventDefault={showChat} />
|
<img src={logoInvite} alt="open menu" class="nes-pointer" on:click|preventDefault={showInvite} />
|
||||||
|
<img src={logoRegister} alt="open menu" class="nes-pointer" on:click|preventDefault={register} />
|
||||||
|
{:else}
|
||||||
|
<img src={logoWA} alt="open menu" class="nes-pointer" on:click|preventDefault={showMenu} />
|
||||||
|
<img src={logoTalk} alt="open menu" class="nes-pointer" on:click|preventDefault={showChat} />
|
||||||
|
{/if}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -41,10 +41,10 @@
|
|||||||
gameManager.leaveGame(SelectCharacterSceneName, new SelectCharacterScene());
|
gameManager.leaveGame(SelectCharacterSceneName, new SelectCharacterScene());
|
||||||
}
|
}
|
||||||
|
|
||||||
function logOut() {
|
async function logOut() {
|
||||||
disableMenuStores();
|
disableMenuStores();
|
||||||
loginSceneVisibleStore.set(true);
|
loginSceneVisibleStore.set(true);
|
||||||
connectionManager.logout();
|
return connectionManager.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getProfileUrl() {
|
function getProfileUrl() {
|
||||||
|
@ -33,9 +33,9 @@
|
|||||||
const body = HtmlUtils.querySelectorOrFail("body");
|
const body = HtmlUtils.querySelectorOrFail("body");
|
||||||
if (body) {
|
if (body) {
|
||||||
if (document.fullscreenElement !== null && !fullscreen) {
|
if (document.fullscreenElement !== null && !fullscreen) {
|
||||||
document.exitFullscreen();
|
document.exitFullscreen().catch((e) => console.error(e));
|
||||||
} else {
|
} else {
|
||||||
body.requestFullscreen();
|
body.requestFullscreen().catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
localUserStore.setFullscreen(fullscreen);
|
localUserStore.setFullscreen(fullscreen);
|
||||||
}
|
}
|
||||||
@ -45,14 +45,16 @@
|
|||||||
if (Notification.permission === "granted") {
|
if (Notification.permission === "granted") {
|
||||||
localUserStore.setNotification(notification ? "granted" : "denied");
|
localUserStore.setNotification(notification ? "granted" : "denied");
|
||||||
} else {
|
} else {
|
||||||
Notification.requestPermission().then((response) => {
|
Notification.requestPermission()
|
||||||
if (response === "granted") {
|
.then((response) => {
|
||||||
localUserStore.setNotification(notification ? "granted" : "denied");
|
if (response === "granted") {
|
||||||
} else {
|
localUserStore.setNotification(notification ? "granted" : "denied");
|
||||||
localUserStore.setNotification("denied");
|
} else {
|
||||||
notification = false;
|
localUserStore.setNotification("denied");
|
||||||
}
|
notification = false;
|
||||||
});
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
47
front/src/Components/Modal/LimitRoomModal.svelte
Normal file
47
front/src/Components/Modal/LimitRoomModal.svelte
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<script lang="typescript">
|
||||||
|
import { fly } from "svelte/transition";
|
||||||
|
import { ADMIN_URL } from "../../Enum/EnvironmentVariable";
|
||||||
|
|
||||||
|
function register() {
|
||||||
|
window.open(`${ADMIN_URL}/second-step-register`, "_self");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="limit-map nes-container" transition:fly={{ y: -900, duration: 500 }}>
|
||||||
|
<section>
|
||||||
|
<h2>Limit of your room</h2>
|
||||||
|
<p>Register your account!</p>
|
||||||
|
<p>
|
||||||
|
This map is limited in the time and to continue to use WorkAdventure, you must register your account in our
|
||||||
|
back office.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<button class="nes-btn is-primary" on:click|preventDefault={register}>Register</button>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.limit-map {
|
||||||
|
pointer-events: auto;
|
||||||
|
background: #eceeee;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-top: 10vh;
|
||||||
|
max-height: 80vh;
|
||||||
|
max-width: 80vw;
|
||||||
|
overflow: auto;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-family: "Press Start 2P";
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
p {
|
||||||
|
margin: 15px;
|
||||||
|
font-family: "Press Start 2P";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
90
front/src/Components/Modal/ShareLinkMapModal.svelte
Normal file
90
front/src/Components/Modal/ShareLinkMapModal.svelte
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<script lang="typescript">
|
||||||
|
import { fly } from "svelte/transition";
|
||||||
|
import { showShareLinkMapModalStore } from "../../Stores/ModalStore";
|
||||||
|
|
||||||
|
interface ExtNavigator extends Navigator {
|
||||||
|
canShare?(data?: ShareData): Promise<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const myNavigator: ExtNavigator = window.navigator;
|
||||||
|
const haveNavigatorSharingFeature: boolean =
|
||||||
|
myNavigator && myNavigator.canShare != null && myNavigator.share != null;
|
||||||
|
|
||||||
|
let copied: boolean = false;
|
||||||
|
|
||||||
|
function copyLink() {
|
||||||
|
try {
|
||||||
|
const input: HTMLInputElement = document.getElementById("input-share-link") as HTMLInputElement;
|
||||||
|
input.focus();
|
||||||
|
input.select();
|
||||||
|
document.execCommand("copy");
|
||||||
|
copied = true;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
copied = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function shareLink() {
|
||||||
|
const shareData = { url: location.toString() };
|
||||||
|
|
||||||
|
try {
|
||||||
|
await myNavigator.share(shareData);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error: " + err);
|
||||||
|
copyLink();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
showShareLinkMapModalStore.set(false);
|
||||||
|
copied = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="share-link-map nes-container" transition:fly={{ y: -900, duration: 500 }}>
|
||||||
|
<section>
|
||||||
|
<h2>Invite your friends or colleagues</h2>
|
||||||
|
<p>Share the link of the room!</p>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
{#if haveNavigatorSharingFeature}
|
||||||
|
<input type="hidden" readonly id="input-share-link" value={location.toString()} />
|
||||||
|
<button type="button" class="nes-btn is-primary" on:click={shareLink}>Share</button>
|
||||||
|
{:else}
|
||||||
|
<input type="text" readonly id="input-share-link" value={location.toString()} />
|
||||||
|
<button type="button" class="nes-btn is-primary" on:click={copyLink}>Copy</button>
|
||||||
|
{/if}
|
||||||
|
{#if copied}
|
||||||
|
<p>Copied!</p>
|
||||||
|
{/if}
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<button class="nes-btn" on:click|preventDefault={close}>Close</button>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
div.share-link-map {
|
||||||
|
pointer-events: auto;
|
||||||
|
background: #eceeee;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-top: 10vh;
|
||||||
|
max-height: 80vh;
|
||||||
|
max-width: 80vw;
|
||||||
|
overflow: auto;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-family: "Press Start 2P";
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
p {
|
||||||
|
margin: 15px;
|
||||||
|
font-family: "Press Start 2P";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -6,12 +6,11 @@
|
|||||||
import type { Unsubscriber } from "svelte/store";
|
import type { Unsubscriber } from "svelte/store";
|
||||||
import { playersStore } from "../../Stores/PlayersStore";
|
import { playersStore } from "../../Stores/PlayersStore";
|
||||||
import { connectionManager } from "../../Connexion/ConnectionManager";
|
import { connectionManager } from "../../Connexion/ConnectionManager";
|
||||||
import { GameConnexionTypes } from "../../Url/UrlManager";
|
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
let blockActive = true;
|
let blockActive = true;
|
||||||
let reportActive = !blockActive;
|
let reportActive = !blockActive;
|
||||||
let anonymous: boolean = false;
|
let disableReport: boolean = false;
|
||||||
let userUUID: string | undefined = playersStore.getPlayerById(get(showReportScreenStore).userId)?.userUuid;
|
let userUUID: string | undefined = playersStore.getPlayerById(get(showReportScreenStore).userId)?.userUuid;
|
||||||
let userName = "No name";
|
let userName = "No name";
|
||||||
let unsubscriber: Unsubscriber;
|
let unsubscriber: Unsubscriber;
|
||||||
@ -26,7 +25,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
anonymous = connectionManager.getConnexionType === GameConnexionTypes.anonymous;
|
disableReport = !connectionManager.currentRoom?.canReport ?? true;
|
||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
@ -65,7 +64,7 @@
|
|||||||
<button type="button" class="nes-btn" on:click|preventDefault={close}>X</button>
|
<button type="button" class="nes-btn" on:click|preventDefault={close}>X</button>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
<section class="report-menu-action {anonymous ? 'hidden' : ''}">
|
<section class="report-menu-action {disableReport ? 'hidden' : ''}">
|
||||||
<section class="justify-center">
|
<section class="justify-center">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
afterUpdate(() => {
|
afterUpdate(() => {
|
||||||
audio.play();
|
audio.play().catch((e) => console.error(e));
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1,20 +1,26 @@
|
|||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import { fly } from "svelte/transition";
|
import { fly } from "svelte/transition";
|
||||||
import { userIsAdminStore } from "../../Stores/GameStore";
|
import { userIsAdminStore, limitMapStore } from "../../Stores/GameStore";
|
||||||
import { ADMIN_URL } from "../../Enum/EnvironmentVariable";
|
import { ADMIN_URL } from "../../Enum/EnvironmentVariable";
|
||||||
|
|
||||||
const upgradeLink = ADMIN_URL + "/pricing";
|
const upgradeLink = ADMIN_URL + "/pricing";
|
||||||
|
const registerLink = ADMIN_URL + "/second-step-register";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main class="warningMain" transition:fly={{ y: -200, duration: 500 }}>
|
<main class="warningMain" transition:fly={{ y: -200, duration: 500 }}>
|
||||||
<h2>Warning!</h2>
|
|
||||||
{#if $userIsAdminStore}
|
{#if $userIsAdminStore}
|
||||||
|
<h2>Warning!</h2>
|
||||||
<p>
|
<p>
|
||||||
This world is close to its limit!. You can upgrade its capacity <a href={upgradeLink} target="_blank"
|
This world is close to its limit!. You can upgrade its capacity <a href={upgradeLink} target="_blank"
|
||||||
>here</a
|
>here</a
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
|
{:else if $limitMapStore}
|
||||||
|
<p>
|
||||||
|
This map is available for 2 days. You can register your domain <a href={registerLink}>here</a>!
|
||||||
|
</p>
|
||||||
{:else}
|
{:else}
|
||||||
|
<h2>Warning!</h2>
|
||||||
<p>This world is close to its limit!</p>
|
<p>This world is close to its limit!</p>
|
||||||
{/if}
|
{/if}
|
||||||
</main>
|
</main>
|
||||||
|
BIN
front/src/Components/images/logo-invite-pixel.png
Normal file
BIN
front/src/Components/images/logo-invite-pixel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
BIN
front/src/Components/images/logo-register-pixel.png
Normal file
BIN
front/src/Components/images/logo-register-pixel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 977 B |
@ -1,5 +1,5 @@
|
|||||||
import { Subject } from "rxjs";
|
import { Subject } from "rxjs";
|
||||||
import type { BanUserMessage, SendUserMessage } from "../Messages/generated/messages_pb";
|
import type { BanUserMessage, SendUserMessage } from "../Messages/ts-proto-generated/messages";
|
||||||
|
|
||||||
export enum AdminMessageEventTypes {
|
export enum AdminMessageEventTypes {
|
||||||
admin = "message",
|
admin = "message",
|
||||||
@ -26,8 +26,8 @@ class AdminMessagesService {
|
|||||||
|
|
||||||
onSendusermessage(message: SendUserMessage | BanUserMessage) {
|
onSendusermessage(message: SendUserMessage | BanUserMessage) {
|
||||||
this._messageStream.next({
|
this._messageStream.next({
|
||||||
type: message.getType() as unknown as AdminMessageEventTypes,
|
type: message.type as unknown as AdminMessageEventTypes,
|
||||||
text: message.getMessage(),
|
text: message.message,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,14 @@ import { CharacterTexture, LocalUser } from "./LocalUser";
|
|||||||
import { Room } from "./Room";
|
import { Room } from "./Room";
|
||||||
import { _ServiceWorker } from "../Network/ServiceWorker";
|
import { _ServiceWorker } from "../Network/ServiceWorker";
|
||||||
import { loginSceneVisibleIframeStore } from "../Stores/LoginSceneStore";
|
import { loginSceneVisibleIframeStore } from "../Stores/LoginSceneStore";
|
||||||
import { userIsConnected } from "../Stores/MenuStore";
|
import { userIsConnected, warningContainerStore } from "../Stores/MenuStore";
|
||||||
import { analyticsClient } from "../Administration/AnalyticsClient";
|
import { analyticsClient } from "../Administration/AnalyticsClient";
|
||||||
import { axiosWithRetry } from "./AxiosUtils";
|
import { axiosWithRetry } from "./AxiosUtils";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { isRegisterData } from "../Messages/JsonMessages/RegisterData";
|
import { isRegisterData } from "../Messages/JsonMessages/RegisterData";
|
||||||
import { isAdminApiData } from "../Messages/JsonMessages/AdminApiData";
|
import { isAdminApiData } from "../Messages/JsonMessages/AdminApiData";
|
||||||
|
import { limitMapStore } from "../Stores/GameStore";
|
||||||
|
import { showLimitRoomModalStore } from "../Stores/ModalStore";
|
||||||
|
|
||||||
class ConnectionManager {
|
class ConnectionManager {
|
||||||
private localUser!: LocalUser;
|
private localUser!: LocalUser;
|
||||||
@ -152,11 +154,7 @@ class ConnectionManager {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
urlManager.pushRoomIdToUrl(this._currentRoom);
|
urlManager.pushRoomIdToUrl(this._currentRoom);
|
||||||
} else if (
|
} else if (connexionType === GameConnexionTypes.room || connexionType === GameConnexionTypes.empty) {
|
||||||
connexionType === GameConnexionTypes.organization ||
|
|
||||||
connexionType === GameConnexionTypes.anonymous ||
|
|
||||||
connexionType === GameConnexionTypes.empty
|
|
||||||
) {
|
|
||||||
this.authToken = localUserStore.getAuthToken();
|
this.authToken = localUserStore.getAuthToken();
|
||||||
|
|
||||||
let roomPath: string;
|
let roomPath: string;
|
||||||
@ -188,7 +186,7 @@ class ConnectionManager {
|
|||||||
|
|
||||||
//Set last room visited! (connected or nor, must to be saved in localstorage and cache API)
|
//Set last room visited! (connected or nor, must to be saved in localstorage and cache API)
|
||||||
//use href to keep # value
|
//use href to keep # value
|
||||||
localUserStore.setLastRoomUrl(this._currentRoom.href);
|
await localUserStore.setLastRoomUrl(this._currentRoom.href);
|
||||||
|
|
||||||
//todo: add here some kind of warning if authToken has expired.
|
//todo: add here some kind of warning if authToken has expired.
|
||||||
if (!this.authToken && !this._currentRoom.authenticationMandatory) {
|
if (!this.authToken && !this._currentRoom.authenticationMandatory) {
|
||||||
@ -237,6 +235,17 @@ class ConnectionManager {
|
|||||||
analyticsClient.identifyUser(this.localUser.uuid, this.localUser.email);
|
analyticsClient.identifyUser(this.localUser.uuid, this.localUser.email);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if limit room active test headband
|
||||||
|
if (this._currentRoom.expireOn !== undefined) {
|
||||||
|
warningContainerStore.activateWarningContainer();
|
||||||
|
limitMapStore.set(true);
|
||||||
|
|
||||||
|
//check time of map
|
||||||
|
if (new Date() > this._currentRoom.expireOn) {
|
||||||
|
showLimitRoomModalStore.set(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.serviceWorker = new _ServiceWorker();
|
this.serviceWorker = new _ServiceWorker();
|
||||||
return Promise.resolve(this._currentRoom);
|
return Promise.resolve(this._currentRoom);
|
||||||
}
|
}
|
||||||
@ -280,7 +289,7 @@ class ConnectionManager {
|
|||||||
reject(error);
|
reject(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.onConnectingError((event: CloseEvent) => {
|
connection.connectionErrorStream.subscribe((event: CloseEvent) => {
|
||||||
console.log("An error occurred while connecting to socket server. Retrying");
|
console.log("An error occurred while connecting to socket server. Retrying");
|
||||||
reject(
|
reject(
|
||||||
new Error(
|
new Error(
|
||||||
@ -292,7 +301,7 @@ class ConnectionManager {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.onConnect((connect: OnConnectInterface) => {
|
connection.roomJoinedMessageStream.subscribe((connect: OnConnectInterface) => {
|
||||||
resolve(connect);
|
resolve(connect);
|
||||||
});
|
});
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
@ -301,7 +310,7 @@ class ConnectionManager {
|
|||||||
this.reconnectingTimeout = setTimeout(() => {
|
this.reconnectingTimeout = setTimeout(() => {
|
||||||
//todo: allow a way to break recursion?
|
//todo: allow a way to break recursion?
|
||||||
//todo: find a way to avoid recursive function. Otherwise, the call stack will grow indefinitely.
|
//todo: find a way to avoid recursive function. Otherwise, the call stack will grow indefinitely.
|
||||||
this.connectToRoomSocket(roomUrl, name, characterLayers, position, viewport, companion).then(
|
void this.connectToRoomSocket(roomUrl, name, characterLayers, position, viewport, companion).then(
|
||||||
(connection) => resolve(connection)
|
(connection) => resolve(connection)
|
||||||
);
|
);
|
||||||
}, 4000 + Math.floor(Math.random() * 2000));
|
}, 4000 + Math.floor(Math.random() * 2000));
|
||||||
|
@ -1,44 +1,12 @@
|
|||||||
import type { SignalData } from "simple-peer";
|
import type { SignalData } from "simple-peer";
|
||||||
import type { RoomConnection } from "./RoomConnection";
|
import type { RoomConnection } from "./RoomConnection";
|
||||||
import type { BodyResourceDescriptionInterface } from "../Phaser/Entity/PlayerTextures";
|
import type { BodyResourceDescriptionInterface } from "../Phaser/Entity/PlayerTextures";
|
||||||
|
import { PositionMessage_Direction } from "../Messages/ts-proto-generated/messages";
|
||||||
export enum EventMessage {
|
|
||||||
CONNECT = "connect",
|
|
||||||
WEBRTC_SIGNAL = "webrtc-signal",
|
|
||||||
WEBRTC_SCREEN_SHARING_SIGNAL = "webrtc-screen-sharing-signal",
|
|
||||||
WEBRTC_START = "webrtc-start",
|
|
||||||
//START_ROOM = "start-room", // From server to client: list of all room users/groups/items
|
|
||||||
JOIN_ROOM = "join-room", // bi-directional
|
|
||||||
USER_POSITION = "user-position", // From client to server
|
|
||||||
USER_MOVED = "user-moved", // From server to client
|
|
||||||
USER_LEFT = "user-left", // From server to client
|
|
||||||
MESSAGE_ERROR = "message-error",
|
|
||||||
WEBRTC_DISCONNECT = "webrtc-disconect",
|
|
||||||
GROUP_CREATE_UPDATE = "group-create-update",
|
|
||||||
GROUP_DELETE = "group-delete",
|
|
||||||
SET_PLAYER_DETAILS = "set-player-details", // Send the name and character to the server (on connect), receive back the id.
|
|
||||||
ITEM_EVENT = "item-event",
|
|
||||||
USER_DETAILS_UPDATED = "user-details-updated",
|
|
||||||
|
|
||||||
CONNECT_ERROR = "connect_error",
|
|
||||||
CONNECTING_ERROR = "connecting_error",
|
|
||||||
SET_SILENT = "set_silent", // Set or unset the silent mode for this user.
|
|
||||||
SET_VIEWPORT = "set-viewport",
|
|
||||||
BATCH = "batch",
|
|
||||||
|
|
||||||
PLAY_GLOBAL_MESSAGE = "play-global-message",
|
|
||||||
STOP_GLOBAL_MESSAGE = "stop-global-message",
|
|
||||||
|
|
||||||
TELEPORT = "teleport",
|
|
||||||
USER_MESSAGE = "user-message",
|
|
||||||
START_JITSI_ROOM = "start-jitsi-room",
|
|
||||||
SET_VARIABLE = "set-variable",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PointInterface {
|
export interface PointInterface {
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
direction: string;
|
direction: string; // TODO: modify this to the enum from ts-proto
|
||||||
moving: boolean;
|
moving: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
import { Subject } from "rxjs";
|
|
||||||
|
|
||||||
interface EmoteEvent {
|
|
||||||
userId: number;
|
|
||||||
emote: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
class EmoteEventStream {
|
|
||||||
private _stream: Subject<EmoteEvent> = new Subject();
|
|
||||||
public stream = this._stream.asObservable();
|
|
||||||
|
|
||||||
fire(userId: number, emote: string) {
|
|
||||||
this._stream.next({ userId, emote });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const emoteEventStream = new EmoteEventStream();
|
|
@ -22,8 +22,8 @@ const nonce = "nonce";
|
|||||||
const notification = "notificationPermission";
|
const notification = "notificationPermission";
|
||||||
const code = "code";
|
const code = "code";
|
||||||
const cameraSetup = "cameraSetup";
|
const cameraSetup = "cameraSetup";
|
||||||
|
|
||||||
const cacheAPIIndex = "workavdenture-cache";
|
const cacheAPIIndex = "workavdenture-cache";
|
||||||
|
const userProperties = "user-properties";
|
||||||
|
|
||||||
class LocalUserStore {
|
class LocalUserStore {
|
||||||
saveUser(localUser: LocalUser) {
|
saveUser(localUser: LocalUser) {
|
||||||
@ -136,13 +136,12 @@ class LocalUserStore {
|
|||||||
return localStorage.getItem(ignoreFollowRequests) === "true";
|
return localStorage.getItem(ignoreFollowRequests) === "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
setLastRoomUrl(roomUrl: string): void {
|
async setLastRoomUrl(roomUrl: string): Promise<void> {
|
||||||
localStorage.setItem(lastRoomUrl, roomUrl.toString());
|
localStorage.setItem(lastRoomUrl, roomUrl.toString());
|
||||||
if ("caches" in window) {
|
if ("caches" in window) {
|
||||||
caches.open(cacheAPIIndex).then((cache) => {
|
const cache = await caches.open(cacheAPIIndex);
|
||||||
const stringResponse = new Response(JSON.stringify({ roomUrl }));
|
const stringResponse = new Response(JSON.stringify({ roomUrl }));
|
||||||
cache.put(`/${lastRoomUrl}`, stringResponse);
|
await cache.put(`/${lastRoomUrl}`, stringResponse);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getLastRoomUrl(): string {
|
getLastRoomUrl(): string {
|
||||||
@ -220,6 +219,27 @@ class LocalUserStore {
|
|||||||
const cameraSetupValues = localStorage.getItem(cameraSetup);
|
const cameraSetupValues = localStorage.getItem(cameraSetup);
|
||||||
return cameraSetupValues != undefined ? JSON.parse(cameraSetupValues) : undefined;
|
return cameraSetupValues != undefined ? JSON.parse(cameraSetupValues) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAllUserProperties(): Map<string, unknown> {
|
||||||
|
const result = new Map<string, string>();
|
||||||
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
|
const key = localStorage.key(i);
|
||||||
|
if (key) {
|
||||||
|
if (key.startsWith(userProperties + "_")) {
|
||||||
|
const value = localStorage.getItem(key);
|
||||||
|
if (value) {
|
||||||
|
const userKey = key.substr((userProperties + "_").length);
|
||||||
|
result.set(userKey, JSON.parse(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUserProperty(name: string, value: unknown): void {
|
||||||
|
localStorage.setItem(userProperties + "_" + name, JSON.stringify(value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const localUserStore = new LocalUserStore();
|
export const localUserStore = new LocalUserStore();
|
||||||
|
@ -18,7 +18,10 @@ export interface RoomRedirect {
|
|||||||
|
|
||||||
export class Room {
|
export class Room {
|
||||||
public readonly id: string;
|
public readonly id: string;
|
||||||
public readonly isPublic: boolean;
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
private readonly isPublic: boolean;
|
||||||
private _authenticationMandatory: boolean = DISABLE_ANONYMOUS;
|
private _authenticationMandatory: boolean = DISABLE_ANONYMOUS;
|
||||||
private _iframeAuthentication?: string = OPID_LOGIN_SCREEN_PROVIDER;
|
private _iframeAuthentication?: string = OPID_LOGIN_SCREEN_PROVIDER;
|
||||||
private _mapUrl: string | undefined;
|
private _mapUrl: string | undefined;
|
||||||
@ -27,6 +30,8 @@ export class Room {
|
|||||||
private readonly _search: URLSearchParams;
|
private readonly _search: URLSearchParams;
|
||||||
private _contactPage: string | undefined;
|
private _contactPage: string | undefined;
|
||||||
private _group: string | null = null;
|
private _group: string | null = null;
|
||||||
|
private _expireOn: Date | undefined;
|
||||||
|
private _canReport: boolean = false;
|
||||||
|
|
||||||
private constructor(private roomUrl: URL) {
|
private constructor(private roomUrl: URL) {
|
||||||
this.id = roomUrl.pathname;
|
this.id = roomUrl.pathname;
|
||||||
@ -34,7 +39,7 @@ export class Room {
|
|||||||
if (this.id.startsWith("/")) {
|
if (this.id.startsWith("/")) {
|
||||||
this.id = this.id.substr(1);
|
this.id = this.id.substr(1);
|
||||||
}
|
}
|
||||||
if (this.id.startsWith("_/")) {
|
if (this.id.startsWith("_/") || this.id.startsWith("*/")) {
|
||||||
this.isPublic = true;
|
this.isPublic = true;
|
||||||
} else if (this.id.startsWith("@/")) {
|
} else if (this.id.startsWith("@/")) {
|
||||||
this.isPublic = false;
|
this.isPublic = false;
|
||||||
@ -121,6 +126,10 @@ export class Room {
|
|||||||
data.authenticationMandatory != null ? data.authenticationMandatory : DISABLE_ANONYMOUS;
|
data.authenticationMandatory != null ? data.authenticationMandatory : DISABLE_ANONYMOUS;
|
||||||
this._iframeAuthentication = data.iframeAuthentication || OPID_LOGIN_SCREEN_PROVIDER;
|
this._iframeAuthentication = data.iframeAuthentication || OPID_LOGIN_SCREEN_PROVIDER;
|
||||||
this._contactPage = data.contactPage || CONTACT_URL;
|
this._contactPage = data.contactPage || CONTACT_URL;
|
||||||
|
if (data.expireOn) {
|
||||||
|
this._expireOn = new Date(data.expireOn);
|
||||||
|
}
|
||||||
|
this._canReport = data.canReport ?? false;
|
||||||
return new MapDetail(data.mapUrl, data.textures);
|
return new MapDetail(data.mapUrl, data.textures);
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Data received by the /map endpoint of the Pusher is not in a valid format.");
|
throw new Error("Data received by the /map endpoint of the Pusher is not in a valid format.");
|
||||||
@ -143,6 +152,8 @@ export class Room {
|
|||||||
* Instance name is:
|
* Instance name is:
|
||||||
* - In a public URL: the second part of the URL ( _/[instance]/map.json)
|
* - In a public URL: the second part of the URL ( _/[instance]/map.json)
|
||||||
* - In a private URL: [organizationId/worldId]
|
* - In a private URL: [organizationId/worldId]
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public getInstance(): string {
|
public getInstance(): string {
|
||||||
if (this.instance !== undefined) {
|
if (this.instance !== undefined) {
|
||||||
@ -150,7 +161,7 @@ export class Room {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.isPublic) {
|
if (this.isPublic) {
|
||||||
const match = /_\/([^/]+)\/.+/.exec(this.id);
|
const match = /[_*]\/([^/]+)\/.+/.exec(this.id);
|
||||||
if (!match) throw new Error('Could not extract instance from "' + this.id + '"');
|
if (!match) throw new Error('Could not extract instance from "' + this.id + '"');
|
||||||
this.instance = match[1];
|
this.instance = match[1];
|
||||||
return this.instance;
|
return this.instance;
|
||||||
@ -222,4 +233,12 @@ export class Room {
|
|||||||
get group(): string | null {
|
get group(): string | null {
|
||||||
return this._group;
|
return this._group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get expireOn(): Date | undefined {
|
||||||
|
return this._expireOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
get canReport(): boolean {
|
||||||
|
return this._canReport;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,12 +0,0 @@
|
|||||||
import { Subject } from "rxjs";
|
|
||||||
|
|
||||||
class WorldFullMessageStream {
|
|
||||||
private _stream: Subject<string | null> = new Subject<string | null>();
|
|
||||||
public stream = this._stream.asObservable();
|
|
||||||
|
|
||||||
onMessage(message?: string) {
|
|
||||||
this._stream.next(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const worldFullMessageStream = new WorldFullMessageStream();
|
|
1
front/src/Messages/.gitignore
vendored
1
front/src/Messages/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
/generated/
|
|
1
front/src/Messages/ts-proto-generated/.gitignore
vendored
Normal file
1
front/src/Messages/ts-proto-generated/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*
|
@ -1,21 +1,21 @@
|
|||||||
import { PositionMessage } from "../Messages/generated/messages_pb";
|
import { PositionMessage, PositionMessage_Direction } from "../Messages/ts-proto-generated/messages";
|
||||||
import Direction = PositionMessage.Direction;
|
|
||||||
import type { PointInterface } from "../Connexion/ConnexionModels";
|
import type { PointInterface } from "../Connexion/ConnexionModels";
|
||||||
|
|
||||||
export class ProtobufClientUtils {
|
export class ProtobufClientUtils {
|
||||||
public static toPointInterface(position: PositionMessage): PointInterface {
|
public static toPointInterface(position: PositionMessage): PointInterface {
|
||||||
let direction: string;
|
let direction: string;
|
||||||
switch (position.getDirection()) {
|
switch (position.direction) {
|
||||||
case Direction.UP:
|
case PositionMessage_Direction.UP:
|
||||||
direction = "up";
|
direction = "up";
|
||||||
break;
|
break;
|
||||||
case Direction.DOWN:
|
case PositionMessage_Direction.DOWN:
|
||||||
direction = "down";
|
direction = "down";
|
||||||
break;
|
break;
|
||||||
case Direction.LEFT:
|
case PositionMessage_Direction.LEFT:
|
||||||
direction = "left";
|
direction = "left";
|
||||||
break;
|
break;
|
||||||
case Direction.RIGHT:
|
case PositionMessage_Direction.RIGHT:
|
||||||
direction = "right";
|
direction = "right";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -24,10 +24,10 @@ export class ProtobufClientUtils {
|
|||||||
|
|
||||||
// sending to all clients in room except sender
|
// sending to all clients in room except sender
|
||||||
return {
|
return {
|
||||||
x: position.getX(),
|
x: position.x,
|
||||||
y: position.getY(),
|
y: position.y,
|
||||||
direction,
|
direction,
|
||||||
moving: position.getMoving(),
|
moving: position.moving,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,13 +41,15 @@ export class Companion extends Container {
|
|||||||
this.companionName = name;
|
this.companionName = name;
|
||||||
this._pictureStore = writable(undefined);
|
this._pictureStore = writable(undefined);
|
||||||
|
|
||||||
texturePromise.then((resource) => {
|
texturePromise
|
||||||
this.addResource(resource);
|
.then((resource) => {
|
||||||
this.invisible = false;
|
this.addResource(resource);
|
||||||
return this.getSnapshot().then((htmlImageElementSrc) => {
|
this.invisible = false;
|
||||||
this._pictureStore.set(htmlImageElementSrc);
|
return this.getSnapshot().then((htmlImageElementSrc) => {
|
||||||
});
|
this._pictureStore.set(htmlImageElementSrc);
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
|
|
||||||
this.scene.physics.world.enableBody(this);
|
this.scene.physics.world.enableBody(this);
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { COMPANION_RESOURCES, CompanionResourceDescriptionInterface } from "./Co
|
|||||||
|
|
||||||
export const getAllCompanionResources = (loader: LoaderPlugin): CompanionResourceDescriptionInterface[] => {
|
export const getAllCompanionResources = (loader: LoaderPlugin): CompanionResourceDescriptionInterface[] => {
|
||||||
COMPANION_RESOURCES.forEach((resource: CompanionResourceDescriptionInterface) => {
|
COMPANION_RESOURCES.forEach((resource: CompanionResourceDescriptionInterface) => {
|
||||||
lazyLoadCompanionResource(loader, resource.name);
|
lazyLoadCompanionResource(loader, resource.name).catch((e) => console.error(e));
|
||||||
});
|
});
|
||||||
|
|
||||||
return COMPANION_RESOURCES;
|
return COMPANION_RESOURCES;
|
||||||
|
@ -72,9 +72,11 @@ export class Loader {
|
|||||||
if (this.loadingText) {
|
if (this.loadingText) {
|
||||||
this.loadingText.destroy();
|
this.loadingText.destroy();
|
||||||
}
|
}
|
||||||
promiseLoadLogoTexture.then((resLoadingImage: Phaser.GameObjects.Image) => {
|
promiseLoadLogoTexture
|
||||||
resLoadingImage.destroy();
|
.then((resLoadingImage: Phaser.GameObjects.Image) => {
|
||||||
});
|
resLoadingImage.destroy();
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
this.progress.destroy();
|
this.progress.destroy();
|
||||||
this.progressContainer.destroy();
|
this.progressContainer.destroy();
|
||||||
if (this.scene instanceof DirtyScene) {
|
if (this.scene instanceof DirtyScene) {
|
||||||
|
@ -16,7 +16,8 @@ export class EmbeddedWebsiteManager {
|
|||||||
if (website === undefined) {
|
if (website === undefined) {
|
||||||
throw new Error('Cannot find embedded website with name "' + name + '"');
|
throw new Error('Cannot find embedded website with name "' + name + '"');
|
||||||
}
|
}
|
||||||
const rect = website.iframe.getBoundingClientRect();
|
|
||||||
|
const scale = website.scale ?? 1;
|
||||||
return {
|
return {
|
||||||
url: website.url,
|
url: website.url,
|
||||||
name: website.name,
|
name: website.name,
|
||||||
@ -26,9 +27,11 @@ export class EmbeddedWebsiteManager {
|
|||||||
position: {
|
position: {
|
||||||
x: website.phaserObject.x,
|
x: website.phaserObject.x,
|
||||||
y: website.phaserObject.y,
|
y: website.phaserObject.y,
|
||||||
width: rect["width"],
|
width: website.phaserObject.width * scale,
|
||||||
height: rect["height"],
|
height: website.phaserObject.height * scale,
|
||||||
},
|
},
|
||||||
|
origin: website.origin,
|
||||||
|
scale: website.scale,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -59,7 +62,9 @@ export class EmbeddedWebsiteManager {
|
|||||||
createEmbeddedWebsiteEvent.position.height,
|
createEmbeddedWebsiteEvent.position.height,
|
||||||
createEmbeddedWebsiteEvent.visible ?? true,
|
createEmbeddedWebsiteEvent.visible ?? true,
|
||||||
createEmbeddedWebsiteEvent.allowApi ?? false,
|
createEmbeddedWebsiteEvent.allowApi ?? false,
|
||||||
createEmbeddedWebsiteEvent.allow ?? ""
|
createEmbeddedWebsiteEvent.allow ?? "",
|
||||||
|
createEmbeddedWebsiteEvent.origin ?? "map",
|
||||||
|
createEmbeddedWebsiteEvent.scale ?? 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -107,10 +112,18 @@ export class EmbeddedWebsiteManager {
|
|||||||
website.phaserObject.y = embeddedWebsiteEvent.y;
|
website.phaserObject.y = embeddedWebsiteEvent.y;
|
||||||
}
|
}
|
||||||
if (embeddedWebsiteEvent?.width !== undefined) {
|
if (embeddedWebsiteEvent?.width !== undefined) {
|
||||||
website.iframe.style.width = embeddedWebsiteEvent.width + "px";
|
website.position.width = embeddedWebsiteEvent.width;
|
||||||
|
website.iframe.style.width = embeddedWebsiteEvent.width / website.phaserObject.scale + "px";
|
||||||
}
|
}
|
||||||
if (embeddedWebsiteEvent?.height !== undefined) {
|
if (embeddedWebsiteEvent?.height !== undefined) {
|
||||||
website.iframe.style.height = embeddedWebsiteEvent.height + "px";
|
website.position.height = embeddedWebsiteEvent.height;
|
||||||
|
website.iframe.style.height = embeddedWebsiteEvent.height / website.phaserObject.scale + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (embeddedWebsiteEvent?.scale !== undefined) {
|
||||||
|
website.phaserObject.scale = embeddedWebsiteEvent.scale;
|
||||||
|
website.iframe.style.width = website.position.width / embeddedWebsiteEvent.scale + "px";
|
||||||
|
website.iframe.style.height = website.position.height / embeddedWebsiteEvent.scale + "px";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -125,7 +138,9 @@ export class EmbeddedWebsiteManager {
|
|||||||
height: number,
|
height: number,
|
||||||
visible: boolean,
|
visible: boolean,
|
||||||
allowApi: boolean,
|
allowApi: boolean,
|
||||||
allow: string
|
allow: string,
|
||||||
|
origin: "map" | "player" | undefined,
|
||||||
|
scale: number | undefined
|
||||||
): void {
|
): void {
|
||||||
if (this.embeddedWebsites.has(name)) {
|
if (this.embeddedWebsites.has(name)) {
|
||||||
throw new Error('An embedded website with the name "' + name + '" already exists in your map');
|
throw new Error('An embedded website with the name "' + name + '" already exists in your map');
|
||||||
@ -135,9 +150,9 @@ export class EmbeddedWebsiteManager {
|
|||||||
name,
|
name,
|
||||||
url,
|
url,
|
||||||
/*x,
|
/*x,
|
||||||
y,
|
y,
|
||||||
width,
|
width,
|
||||||
height,*/
|
height,*/
|
||||||
allow,
|
allow,
|
||||||
allowApi,
|
allowApi,
|
||||||
visible,
|
visible,
|
||||||
@ -147,6 +162,8 @@ export class EmbeddedWebsiteManager {
|
|||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
},
|
},
|
||||||
|
origin,
|
||||||
|
scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
const embeddedWebsite = this.doCreateEmbeddedWebsite(embeddedWebsiteEvent, visible);
|
const embeddedWebsite = this.doCreateEmbeddedWebsite(embeddedWebsiteEvent, visible);
|
||||||
@ -161,22 +178,43 @@ export class EmbeddedWebsiteManager {
|
|||||||
const absoluteUrl = new URL(embeddedWebsiteEvent.url, this.gameScene.MapUrlFile).toString();
|
const absoluteUrl = new URL(embeddedWebsiteEvent.url, this.gameScene.MapUrlFile).toString();
|
||||||
|
|
||||||
const iframe = document.createElement("iframe");
|
const iframe = document.createElement("iframe");
|
||||||
|
const scale = embeddedWebsiteEvent.scale ?? 1;
|
||||||
|
|
||||||
iframe.src = absoluteUrl;
|
iframe.src = absoluteUrl;
|
||||||
iframe.tabIndex = -1;
|
iframe.tabIndex = -1;
|
||||||
iframe.style.width = embeddedWebsiteEvent.position.width + "px";
|
iframe.style.width = embeddedWebsiteEvent.position.width / scale + "px";
|
||||||
iframe.style.height = embeddedWebsiteEvent.position.height + "px";
|
iframe.style.height = embeddedWebsiteEvent.position.height / scale + "px";
|
||||||
iframe.style.margin = "0";
|
iframe.style.margin = "0";
|
||||||
iframe.style.padding = "0";
|
iframe.style.padding = "0";
|
||||||
iframe.style.border = "none";
|
iframe.style.border = "none";
|
||||||
|
|
||||||
|
const domElement = new DOMElement(
|
||||||
|
this.gameScene,
|
||||||
|
embeddedWebsiteEvent.position.x,
|
||||||
|
embeddedWebsiteEvent.position.y,
|
||||||
|
iframe
|
||||||
|
);
|
||||||
|
domElement.setOrigin(0, 0);
|
||||||
|
if (embeddedWebsiteEvent.scale) {
|
||||||
|
domElement.scale = embeddedWebsiteEvent.scale;
|
||||||
|
}
|
||||||
|
domElement.setVisible(visible);
|
||||||
|
|
||||||
|
switch (embeddedWebsiteEvent.origin) {
|
||||||
|
case "player":
|
||||||
|
this.gameScene.CurrentPlayer.add(domElement);
|
||||||
|
break;
|
||||||
|
case "map":
|
||||||
|
default:
|
||||||
|
this.gameScene.add.existing(domElement);
|
||||||
|
}
|
||||||
|
|
||||||
const embeddedWebsite = {
|
const embeddedWebsite = {
|
||||||
...embeddedWebsiteEvent,
|
...embeddedWebsiteEvent,
|
||||||
phaserObject: this.gameScene.add
|
phaserObject: domElement,
|
||||||
.dom(embeddedWebsiteEvent.position.x, embeddedWebsiteEvent.position.y, iframe)
|
|
||||||
.setVisible(visible)
|
|
||||||
.setOrigin(0, 0),
|
|
||||||
iframe: iframe,
|
iframe: iframe,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (embeddedWebsiteEvent.allowApi) {
|
if (embeddedWebsiteEvent.allowApi) {
|
||||||
iframeListener.registerIframe(iframe);
|
iframeListener.registerIframe(iframe);
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { emoteEventStream } from "../../Connexion/EmoteEventStream";
|
|
||||||
import type { GameScene } from "./GameScene";
|
import type { GameScene } from "./GameScene";
|
||||||
import type { Subscription } from "rxjs";
|
import type { Subscription } from "rxjs";
|
||||||
|
import type { RoomConnection } from "../../Connexion/RoomConnection";
|
||||||
|
|
||||||
export class EmoteManager {
|
export class EmoteManager {
|
||||||
private subscription: Subscription;
|
private subscription: Subscription;
|
||||||
|
|
||||||
constructor(private scene: GameScene) {
|
constructor(private scene: GameScene, private connection: RoomConnection) {
|
||||||
this.subscription = emoteEventStream.stream.subscribe((event) => {
|
this.subscription = connection.emoteEventMessageStream.subscribe((event) => {
|
||||||
const actor = this.scene.MapPlayersByKey.get(event.userId);
|
const actor = this.scene.MapPlayersByKey.get(event.actorUserId);
|
||||||
if (actor) {
|
if (actor) {
|
||||||
actor.playEmote(event.emote);
|
actor.playEmote(event.emote);
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ export class GameMapPropertiesListener {
|
|||||||
.then((coWebsite) => {
|
.then((coWebsite) => {
|
||||||
const coWebsiteOpen = this.coWebsitesOpenByLayer.get(layer);
|
const coWebsiteOpen = this.coWebsitesOpenByLayer.get(layer);
|
||||||
if (coWebsiteOpen && coWebsiteOpen.state === OpenCoWebsiteState.MUST_BE_CLOSE) {
|
if (coWebsiteOpen && coWebsiteOpen.state === OpenCoWebsiteState.MUST_BE_CLOSE) {
|
||||||
coWebsiteManager.closeCoWebsite(coWebsite);
|
coWebsiteManager.closeCoWebsite(coWebsite).catch((e) => console.error(e));
|
||||||
this.coWebsitesOpenByLayer.delete(layer);
|
this.coWebsitesOpenByLayer.delete(layer);
|
||||||
this.coWebsitesActionTriggerByLayer.delete(layer);
|
this.coWebsitesActionTriggerByLayer.delete(layer);
|
||||||
} else {
|
} else {
|
||||||
@ -132,7 +132,8 @@ export class GameMapPropertiesListener {
|
|||||||
state: OpenCoWebsiteState.OPENED,
|
state: OpenCoWebsiteState.OPENED,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
|
|
||||||
layoutManagerActionStore.removeAction(actionUuid);
|
layoutManagerActionStore.removeAction(actionUuid);
|
||||||
};
|
};
|
||||||
@ -198,7 +199,7 @@ export class GameMapPropertiesListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (coWebsiteOpen.coWebsite !== undefined) {
|
if (coWebsiteOpen.coWebsite !== undefined) {
|
||||||
coWebsiteManager.closeCoWebsite(coWebsiteOpen.coWebsite);
|
coWebsiteManager.closeCoWebsite(coWebsiteOpen.coWebsite).catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.coWebsitesOpenByLayer.delete(layer);
|
this.coWebsitesOpenByLayer.delete(layer);
|
||||||
|
@ -40,7 +40,6 @@ import { ReconnectingSceneName } from "../Reconnecting/ReconnectingScene";
|
|||||||
import { GameMap } from "./GameMap";
|
import { GameMap } from "./GameMap";
|
||||||
import { PlayerMovement } from "./PlayerMovement";
|
import { PlayerMovement } from "./PlayerMovement";
|
||||||
import { PlayersPositionInterpolator } from "./PlayersPositionInterpolator";
|
import { PlayersPositionInterpolator } from "./PlayersPositionInterpolator";
|
||||||
import { worldFullMessageStream } from "../../Connexion/WorldFullMessageStream";
|
|
||||||
import { DirtyScene } from "./DirtyScene";
|
import { DirtyScene } from "./DirtyScene";
|
||||||
import { TextUtils } from "../Components/TextUtils";
|
import { TextUtils } from "../Components/TextUtils";
|
||||||
import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick";
|
import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick";
|
||||||
@ -60,7 +59,6 @@ import type {
|
|||||||
PositionInterface,
|
PositionInterface,
|
||||||
RoomJoinedMessageInterface,
|
RoomJoinedMessageInterface,
|
||||||
} from "../../Connexion/ConnexionModels";
|
} from "../../Connexion/ConnexionModels";
|
||||||
import type { UserMovedMessage } from "../../Messages/generated/messages_pb";
|
|
||||||
import type { RoomConnection } from "../../Connexion/RoomConnection";
|
import type { RoomConnection } from "../../Connexion/RoomConnection";
|
||||||
import type { ActionableItem } from "../Items/ActionableItem";
|
import type { ActionableItem } from "../Items/ActionableItem";
|
||||||
import type { ItemFactoryInterface } from "../Items/ItemFactoryInterface";
|
import type { ItemFactoryInterface } from "../Items/ItemFactoryInterface";
|
||||||
@ -90,9 +88,10 @@ import SpriteSheetFile = Phaser.Loader.FileTypes.SpriteSheetFile;
|
|||||||
import { deepCopy } from "deep-copy-ts";
|
import { deepCopy } from "deep-copy-ts";
|
||||||
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
|
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
|
||||||
import { MapStore } from "../../Stores/Utils/MapStore";
|
import { MapStore } from "../../Stores/Utils/MapStore";
|
||||||
import { SetPlayerDetailsMessage } from "../../Messages/generated/messages_pb";
|
|
||||||
import { followUsersColorStore, followUsersStore } from "../../Stores/FollowStore";
|
import { followUsersColorStore, followUsersStore } from "../../Stores/FollowStore";
|
||||||
import { getColorRgbFromHue } from "../../WebRtc/ColorGenerator";
|
import { getColorRgbFromHue } from "../../WebRtc/ColorGenerator";
|
||||||
|
import Camera = Phaser.Cameras.Scene2D.Camera;
|
||||||
|
import type { WasCameraUpdatedEvent } from "../../Api/Events/WasCameraUpdatedEvent";
|
||||||
|
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
initPosition: PointInterface | null;
|
initPosition: PointInterface | null;
|
||||||
@ -210,6 +209,8 @@ export class GameScene extends DirtyScene {
|
|||||||
private objectsByType = new Map<string, ITiledMapObject[]>();
|
private objectsByType = new Map<string, ITiledMapObject[]>();
|
||||||
private embeddedWebsiteManager!: EmbeddedWebsiteManager;
|
private embeddedWebsiteManager!: EmbeddedWebsiteManager;
|
||||||
private loader: Loader;
|
private loader: Loader;
|
||||||
|
private lastCameraEvent: WasCameraUpdatedEvent | undefined;
|
||||||
|
private firstCameraUpdateSent: boolean = false;
|
||||||
|
|
||||||
constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) {
|
constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) {
|
||||||
super({
|
super({
|
||||||
@ -240,7 +241,7 @@ export class GameScene extends DirtyScene {
|
|||||||
const textures = localUser?.textures;
|
const textures = localUser?.textures;
|
||||||
if (textures) {
|
if (textures) {
|
||||||
for (const texture of textures) {
|
for (const texture of textures) {
|
||||||
loadCustomTexture(this.load, texture);
|
loadCustomTexture(this.load, texture).catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +268,7 @@ export class GameScene extends DirtyScene {
|
|||||||
this.load.on(
|
this.load.on(
|
||||||
"filecomplete-tilemapJSON-" + this.MapUrlFile,
|
"filecomplete-tilemapJSON-" + this.MapUrlFile,
|
||||||
(key: string, type: string, data: unknown) => {
|
(key: string, type: string, data: unknown) => {
|
||||||
this.onMapLoad(data);
|
this.onMapLoad(data).catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@ -291,14 +292,14 @@ export class GameScene extends DirtyScene {
|
|||||||
this.load.on(
|
this.load.on(
|
||||||
"filecomplete-tilemapJSON-" + this.MapUrlFile,
|
"filecomplete-tilemapJSON-" + this.MapUrlFile,
|
||||||
(key: string, type: string, data: unknown) => {
|
(key: string, type: string, data: unknown) => {
|
||||||
this.onMapLoad(data);
|
this.onMapLoad(data).catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// If the map has already been loaded as part of another GameScene, the "on load" event will not be triggered.
|
// If the map has already been loaded as part of another GameScene, the "on load" event will not be triggered.
|
||||||
// In this case, we check in the cache to see if the map is here and trigger the event manually.
|
// In this case, we check in the cache to see if the map is here and trigger the event manually.
|
||||||
if (this.cache.tilemap.exists(this.MapUrlFile)) {
|
if (this.cache.tilemap.exists(this.MapUrlFile)) {
|
||||||
const data = this.cache.tilemap.get(this.MapUrlFile);
|
const data = this.cache.tilemap.get(this.MapUrlFile);
|
||||||
this.onMapLoad(data);
|
this.onMapLoad(data).catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -319,7 +320,7 @@ export class GameScene extends DirtyScene {
|
|||||||
});
|
});
|
||||||
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) => {
|
||||||
this.onMapLoad(data);
|
this.onMapLoad(data).catch((e) => console.error(e));
|
||||||
});
|
});
|
||||||
//TODO strategy to add access token
|
//TODO strategy to add access token
|
||||||
this.load.tilemapTiledJSON(this.MapUrlFile, this.MapUrlFile);
|
this.load.tilemapTiledJSON(this.MapUrlFile, this.MapUrlFile);
|
||||||
@ -327,7 +328,7 @@ export class GameScene extends DirtyScene {
|
|||||||
// In this case, we check in the cache to see if the map is here and trigger the event manually.
|
// In this case, we check in the cache to see if the map is here and trigger the event manually.
|
||||||
if (this.cache.tilemap.exists(this.MapUrlFile)) {
|
if (this.cache.tilemap.exists(this.MapUrlFile)) {
|
||||||
const data = this.cache.tilemap.get(this.MapUrlFile);
|
const data = this.cache.tilemap.get(this.MapUrlFile);
|
||||||
this.onMapLoad(data);
|
this.onMapLoad(data).catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
//eslint-disable-next-line @typescript-eslint/no-explicit-any
|
//eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@ -405,21 +406,23 @@ export class GameScene extends DirtyScene {
|
|||||||
this.load.on("complete", () => {
|
this.load.on("complete", () => {
|
||||||
// FIXME: the factory might fail because the resources might not be loaded yet...
|
// FIXME: the factory might fail because the resources might not be loaded yet...
|
||||||
// We would need to add a loader ended event in addition to the createPromise
|
// We would need to add a loader ended event in addition to the createPromise
|
||||||
this.createPromise.then(async () => {
|
this.createPromise
|
||||||
itemFactory.create(this);
|
.then(async () => {
|
||||||
|
itemFactory.create(this);
|
||||||
|
|
||||||
const roomJoinedAnswer = await this.connectionAnswerPromise;
|
const roomJoinedAnswer = await this.connectionAnswerPromise;
|
||||||
|
|
||||||
for (const object of objectsOfType) {
|
for (const object of objectsOfType) {
|
||||||
// TODO: we should pass here a factory to create sprites (maybe?)
|
// TODO: we should pass here a factory to create sprites (maybe?)
|
||||||
|
|
||||||
// Do we have a state for this object?
|
// Do we have a state for this object?
|
||||||
const state = roomJoinedAnswer.items[object.id];
|
const state = roomJoinedAnswer.items[object.id];
|
||||||
|
|
||||||
const actionableItem = itemFactory.factory(this, object, state);
|
const actionableItem = itemFactory.factory(this, object, state);
|
||||||
this.actionableItems.set(actionableItem.getId(), actionableItem);
|
this.actionableItems.set(actionableItem.getId(), actionableItem);
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -448,10 +451,6 @@ export class GameScene extends DirtyScene {
|
|||||||
this.pinchManager = new PinchManager(this);
|
this.pinchManager = new PinchManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.messageSubscription = worldFullMessageStream.stream.subscribe((message) =>
|
|
||||||
this.showWorldFullError(message)
|
|
||||||
);
|
|
||||||
|
|
||||||
const playerName = gameManager.getPlayerName();
|
const playerName = gameManager.getPlayerName();
|
||||||
if (!playerName) {
|
if (!playerName) {
|
||||||
throw "playerName is not set";
|
throw "playerName is not set";
|
||||||
@ -489,11 +488,11 @@ export class GameScene extends DirtyScene {
|
|||||||
if (exitSceneUrl !== undefined) {
|
if (exitSceneUrl !== undefined) {
|
||||||
this.loadNextGame(
|
this.loadNextGame(
|
||||||
Room.getRoomPathFromExitSceneUrl(exitSceneUrl, window.location.toString(), this.MapUrlFile)
|
Room.getRoomPathFromExitSceneUrl(exitSceneUrl, window.location.toString(), this.MapUrlFile)
|
||||||
);
|
).catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
const exitUrl = this.getExitUrl(layer);
|
const exitUrl = this.getExitUrl(layer);
|
||||||
if (exitUrl !== undefined) {
|
if (exitUrl !== undefined) {
|
||||||
this.loadNextGameFromExitUrl(exitUrl);
|
this.loadNextGameFromExitUrl(exitUrl).catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (layer.type === "objectgroup") {
|
if (layer.type === "objectgroup") {
|
||||||
@ -523,7 +522,9 @@ export class GameScene extends DirtyScene {
|
|||||||
object.height,
|
object.height,
|
||||||
object.visible,
|
object.visible,
|
||||||
allowApi ?? false,
|
allowApi ?? false,
|
||||||
""
|
"",
|
||||||
|
"map",
|
||||||
|
1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -531,7 +532,7 @@ export class GameScene extends DirtyScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.gameMap.exitUrls.forEach((exitUrl) => {
|
this.gameMap.exitUrls.forEach((exitUrl) => {
|
||||||
this.loadNextGameFromExitUrl(exitUrl);
|
this.loadNextGameFromExitUrl(exitUrl).catch((e) => console.error(e));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.startPositionCalculator = new StartPositionCalculator(
|
this.startPositionCalculator = new StartPositionCalculator(
|
||||||
@ -552,7 +553,10 @@ export class GameScene extends DirtyScene {
|
|||||||
mediaManager.setUserInputManager(this.userInputManager);
|
mediaManager.setUserInputManager(this.userInputManager);
|
||||||
|
|
||||||
if (localUserStore.getFullscreen()) {
|
if (localUserStore.getFullscreen()) {
|
||||||
document.querySelector("body")?.requestFullscreen();
|
document
|
||||||
|
.querySelector("body")
|
||||||
|
?.requestFullscreen()
|
||||||
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
//notify game manager can to create currentUser in map
|
//notify game manager can to create currentUser in map
|
||||||
@ -617,8 +621,6 @@ export class GameScene extends DirtyScene {
|
|||||||
this.connect();
|
this.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emoteManager = new EmoteManager(this);
|
|
||||||
|
|
||||||
let oldPeerNumber = 0;
|
let oldPeerNumber = 0;
|
||||||
this.peerStoreUnsubscribe = peerStore.subscribe((peers) => {
|
this.peerStoreUnsubscribe = peerStore.subscribe((peers) => {
|
||||||
const newPeerNumber = peers.size;
|
const newPeerNumber = peers.size;
|
||||||
@ -660,9 +662,16 @@ export class GameScene extends DirtyScene {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Promise.all([this.connectionAnswerPromise as Promise<unknown>, ...scriptPromises]).then(() => {
|
Promise.all([this.connectionAnswerPromise as Promise<unknown>, ...scriptPromises])
|
||||||
this.scene.wake();
|
.then(() => {
|
||||||
});
|
this.scene.wake();
|
||||||
|
})
|
||||||
|
.catch((e) =>
|
||||||
|
console.error(
|
||||||
|
"Some scripts failed to load ot the connection failed to establish to WorkAdventure server",
|
||||||
|
e
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -693,7 +702,7 @@ export class GameScene extends DirtyScene {
|
|||||||
playersStore.connectToRoomConnection(this.connection);
|
playersStore.connectToRoomConnection(this.connection);
|
||||||
userIsAdminStore.set(this.connection.hasTag("admin"));
|
userIsAdminStore.set(this.connection.hasTag("admin"));
|
||||||
|
|
||||||
this.connection.onUserJoins((message: MessageUserJoined) => {
|
this.connection.userJoinedMessageStream.subscribe((message) => {
|
||||||
const userMessage: AddPlayerInterface = {
|
const userMessage: AddPlayerInterface = {
|
||||||
userId: message.userId,
|
userId: message.userId,
|
||||||
characterLayers: message.characterLayers,
|
characterLayers: message.characterLayers,
|
||||||
@ -707,31 +716,33 @@ export class GameScene extends DirtyScene {
|
|||||||
this.addPlayer(userMessage);
|
this.addPlayer(userMessage);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.connection.onUserMoved((message: UserMovedMessage) => {
|
this.connection.userMovedMessageStream.subscribe((message) => {
|
||||||
const position = message.getPosition();
|
const position = message.position;
|
||||||
if (position === undefined) {
|
if (position === undefined) {
|
||||||
throw new Error("Position missing from UserMovedMessage");
|
throw new Error("Position missing from UserMovedMessage");
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageUserMoved: MessageUserMovedInterface = {
|
const messageUserMoved: MessageUserMovedInterface = {
|
||||||
userId: message.getUserid(),
|
userId: message.userId,
|
||||||
position: ProtobufClientUtils.toPointInterface(position),
|
position: ProtobufClientUtils.toPointInterface(position),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updatePlayerPosition(messageUserMoved);
|
this.updatePlayerPosition(messageUserMoved);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.connection.onUserLeft((userId: number) => {
|
this.connection.userLeftMessageStream.subscribe((message) => {
|
||||||
this.removePlayer(userId);
|
this.removePlayer(message.userId);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.connection.onGroupUpdatedOrCreated((groupPositionMessage: GroupCreatedUpdatedMessageInterface) => {
|
this.connection.groupUpdateMessageStream.subscribe(
|
||||||
this.shareGroupPosition(groupPositionMessage);
|
(groupPositionMessage: GroupCreatedUpdatedMessageInterface) => {
|
||||||
});
|
this.shareGroupPosition(groupPositionMessage);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
this.connection.onGroupDeleted((groupId: number) => {
|
this.connection.groupDeleteMessageStream.subscribe((message) => {
|
||||||
try {
|
try {
|
||||||
this.deleteGroup(groupId);
|
this.deleteGroup(message.groupId);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
@ -743,7 +754,7 @@ export class GameScene extends DirtyScene {
|
|||||||
this.createSuccessorGameScene(true, true);
|
this.createSuccessorGameScene(true, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.connection.onActionableEvent((message) => {
|
this.connection.itemEventMessageStream.subscribe((message) => {
|
||||||
const item = this.actionableItems.get(message.itemId);
|
const item = this.actionableItems.get(message.itemId);
|
||||||
if (item === undefined) {
|
if (item === undefined) {
|
||||||
console.warn(
|
console.warn(
|
||||||
@ -756,18 +767,29 @@ export class GameScene extends DirtyScene {
|
|||||||
item.fire(message.event, message.state, message.parameters);
|
item.fire(message.event, message.state, message.parameters);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.connection.onPlayerDetailsUpdated((message) => {
|
this.connection.playerDetailsUpdatedMessageStream.subscribe((message) => {
|
||||||
|
if (message.details === undefined) {
|
||||||
|
throw new Error("Malformed message. Missing details in PlayerDetailsUpdatedMessage");
|
||||||
|
}
|
||||||
this.pendingEvents.enqueue({
|
this.pendingEvents.enqueue({
|
||||||
type: "PlayerDetailsUpdated",
|
type: "PlayerDetailsUpdated",
|
||||||
details: message,
|
details: {
|
||||||
|
userId: message.userId,
|
||||||
|
outlineColor: message.details.outlineColor,
|
||||||
|
removeOutlineColor: message.details.removeOutlineColor,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggered when we receive the JWT token to connect to Jitsi
|
* Triggered when we receive the JWT token to connect to Jitsi
|
||||||
*/
|
*/
|
||||||
this.connection.onStartJitsiRoom((jwt, room) => {
|
this.connection.sendJitsiJwtMessageStream.subscribe((message) => {
|
||||||
this.startJitsi(room, jwt);
|
this.startJitsi(message.jitsiRoom, message.jwt);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.messageSubscription = this.connection.worldFullMessageStream.subscribe((message) => {
|
||||||
|
this.showWorldFullError(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
// When connection is performed, let's connect SimplePeer
|
// When connection is performed, let's connect SimplePeer
|
||||||
@ -842,12 +864,15 @@ export class GameScene extends DirtyScene {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.emoteManager = new EmoteManager(this, this.connection);
|
||||||
|
|
||||||
// this.gameMap.onLeaveLayer((layers) => {
|
// this.gameMap.onLeaveLayer((layers) => {
|
||||||
// layers.forEach((layer) => {
|
// layers.forEach((layer) => {
|
||||||
// iframeListener.sendLeaveLayerEvent(layer.name);
|
// iframeListener.sendLeaveLayerEvent(layer.name);
|
||||||
// });
|
// });
|
||||||
// });
|
// });
|
||||||
});
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo: into dedicated classes
|
//todo: into dedicated classes
|
||||||
@ -900,7 +925,7 @@ export class GameScene extends DirtyScene {
|
|||||||
if (newValue) {
|
if (newValue) {
|
||||||
this.onMapExit(
|
this.onMapExit(
|
||||||
Room.getRoomPathFromExitSceneUrl(newValue as string, window.location.toString(), this.MapUrlFile)
|
Room.getRoomPathFromExitSceneUrl(newValue as string, window.location.toString(), this.MapUrlFile)
|
||||||
);
|
).catch((e) => console.error(e));
|
||||||
} else {
|
} else {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
layoutManagerActionStore.removeAction("roomAccessDenied");
|
layoutManagerActionStore.removeAction("roomAccessDenied");
|
||||||
@ -909,7 +934,9 @@ export class GameScene extends DirtyScene {
|
|||||||
});
|
});
|
||||||
this.gameMap.onPropertyChange(GameMapProperties.EXIT_URL, (newValue, oldValue) => {
|
this.gameMap.onPropertyChange(GameMapProperties.EXIT_URL, (newValue, oldValue) => {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
this.onMapExit(Room.getRoomPathFromExitUrl(newValue as string, window.location.toString()));
|
this.onMapExit(Room.getRoomPathFromExitUrl(newValue as string, window.location.toString())).catch((e) =>
|
||||||
|
console.error(e)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
layoutManagerActionStore.removeAction("roomAccessDenied");
|
layoutManagerActionStore.removeAction("roomAccessDenied");
|
||||||
@ -1095,21 +1122,47 @@ ${escapedMessage}
|
|||||||
this.iframeSubscriptionList.push(
|
this.iframeSubscriptionList.push(
|
||||||
iframeListener.playSoundStream.subscribe((playSoundEvent) => {
|
iframeListener.playSoundStream.subscribe((playSoundEvent) => {
|
||||||
const url = new URL(playSoundEvent.url, this.MapUrlFile);
|
const url = new URL(playSoundEvent.url, this.MapUrlFile);
|
||||||
soundManager.playSound(this.load, this.sound, url.toString(), playSoundEvent.config);
|
soundManager
|
||||||
|
.playSound(this.load, this.sound, url.toString(), playSoundEvent.config)
|
||||||
|
.catch((e) => console.error(e));
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.iframeSubscriptionList.push(
|
this.iframeSubscriptionList.push(
|
||||||
iframeListener.stopSoundStream.subscribe((stopSoundEvent) => {
|
iframeListener.trackCameraUpdateStream.subscribe(() => {
|
||||||
const url = new URL(stopSoundEvent.url, this.MapUrlFile);
|
if (!this.firstCameraUpdateSent) {
|
||||||
soundManager.stopSound(this.sound, url.toString());
|
this.cameras.main.on("followupdate", (camera: Camera) => {
|
||||||
|
const cameraEvent: WasCameraUpdatedEvent = {
|
||||||
|
x: camera.worldView.x,
|
||||||
|
y: camera.worldView.y,
|
||||||
|
width: camera.worldView.width,
|
||||||
|
height: camera.worldView.height,
|
||||||
|
zoom: camera.scaleManager.zoom,
|
||||||
|
};
|
||||||
|
if (
|
||||||
|
this.lastCameraEvent?.x == cameraEvent.x &&
|
||||||
|
this.lastCameraEvent?.y == cameraEvent.y &&
|
||||||
|
this.lastCameraEvent?.width == cameraEvent.width &&
|
||||||
|
this.lastCameraEvent?.height == cameraEvent.height &&
|
||||||
|
this.lastCameraEvent?.zoom == cameraEvent.zoom
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastCameraEvent = cameraEvent;
|
||||||
|
iframeListener.sendCameraUpdated(cameraEvent);
|
||||||
|
this.firstCameraUpdateSent = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
iframeListener.sendCameraUpdated(this.cameras.main);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.iframeSubscriptionList.push(
|
this.iframeSubscriptionList.push(
|
||||||
iframeListener.loadSoundStream.subscribe((loadSoundEvent) => {
|
iframeListener.loadSoundStream.subscribe((loadSoundEvent) => {
|
||||||
const url = new URL(loadSoundEvent.url, this.MapUrlFile);
|
const url = new URL(loadSoundEvent.url, this.MapUrlFile);
|
||||||
soundManager.loadSound(this.load, this.sound, url.toString());
|
soundManager.loadSound(this.load, this.sound, url.toString()).catch((e) => console.error(e));
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1120,11 +1173,15 @@ ${escapedMessage}
|
|||||||
);
|
);
|
||||||
this.iframeSubscriptionList.push(
|
this.iframeSubscriptionList.push(
|
||||||
iframeListener.loadPageStream.subscribe((url: string) => {
|
iframeListener.loadPageStream.subscribe((url: string) => {
|
||||||
this.loadNextGameFromExitUrl(url).then(() => {
|
this.loadNextGameFromExitUrl(url)
|
||||||
this.events.once(EVENT_TYPE.POST_UPDATE, () => {
|
.then(() => {
|
||||||
this.onMapExit(Room.getRoomPathFromExitUrl(url, window.location.toString()));
|
this.events.once(EVENT_TYPE.POST_UPDATE, () => {
|
||||||
});
|
this.onMapExit(Room.getRoomPathFromExitUrl(url, window.location.toString())).catch((e) =>
|
||||||
});
|
console.error(e)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
let scriptedBubbleSprite: Sprite;
|
let scriptedBubbleSprite: Sprite;
|
||||||
@ -1165,6 +1222,12 @@ ${escapedMessage}
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.iframeSubscriptionList.push(
|
||||||
|
iframeListener.setPropertyStream.subscribe((setProperty) => {
|
||||||
|
this.setPropertyLayer(setProperty.layerName, setProperty.propertyName, setProperty.propertyValue);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
iframeListener.registerAnswerer("openCoWebsite", async (openCoWebsite, source) => {
|
iframeListener.registerAnswerer("openCoWebsite", async (openCoWebsite, source) => {
|
||||||
if (!source) {
|
if (!source) {
|
||||||
throw new Error("Unknown query source");
|
throw new Error("Unknown query source");
|
||||||
@ -1235,6 +1298,7 @@ ${escapedMessage}
|
|||||||
roomId: this.roomUrl,
|
roomId: this.roomUrl,
|
||||||
tags: this.connection ? this.connection.getAllTags() : [],
|
tags: this.connection ? this.connection.getAllTags() : [],
|
||||||
variables: this.sharedVariablesManager.variables,
|
variables: this.sharedVariablesManager.variables,
|
||||||
|
playerVariables: localUserStore.getAllUserProperties(),
|
||||||
userRoomToken: this.connection ? this.connection.userRoomToken : "",
|
userRoomToken: this.connection ? this.connection.userRoomToken : "",
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -1325,6 +1389,22 @@ ${escapedMessage}
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
iframeListener.registerAnswerer("setVariable", (event, source) => {
|
||||||
|
switch (event.target) {
|
||||||
|
case "global": {
|
||||||
|
this.sharedVariablesManager.setVariable(event, source);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "player": {
|
||||||
|
localUserStore.setUserProperty(event.key, event.value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
const _exhaustiveCheck: never = event.target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
iframeListener.registerAnswerer("removeActionMessage", (message) => {
|
iframeListener.registerAnswerer("removeActionMessage", (message) => {
|
||||||
layoutManagerActionStore.removeAction(message.uuid);
|
layoutManagerActionStore.removeAction(message.uuid);
|
||||||
});
|
});
|
||||||
@ -1343,6 +1423,13 @@ ${escapedMessage}
|
|||||||
this.CurrentPlayer.removeOutlineColor();
|
this.CurrentPlayer.removeOutlineColor();
|
||||||
this.connection?.emitPlayerOutlineColor(null);
|
this.connection?.emitPlayerOutlineColor(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
iframeListener.registerAnswerer("getPlayerPosition", () => {
|
||||||
|
return {
|
||||||
|
x: this.CurrentPlayer.x,
|
||||||
|
y: this.CurrentPlayer.y,
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private setPropertyLayer(
|
private setPropertyLayer(
|
||||||
@ -1351,7 +1438,7 @@ ${escapedMessage}
|
|||||||
propertyValue: string | number | boolean | undefined
|
propertyValue: string | number | boolean | undefined
|
||||||
): void {
|
): void {
|
||||||
if (propertyName === GameMapProperties.EXIT_URL && typeof propertyValue === "string") {
|
if (propertyName === GameMapProperties.EXIT_URL && typeof propertyValue === "string") {
|
||||||
this.loadNextGameFromExitUrl(propertyValue);
|
this.loadNextGameFromExitUrl(propertyValue).catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
this.gameMap.setLayerProperty(layerName, propertyName, propertyValue);
|
this.gameMap.setLayerProperty(layerName, propertyName, propertyValue);
|
||||||
}
|
}
|
||||||
@ -1436,7 +1523,7 @@ ${escapedMessage}
|
|||||||
|
|
||||||
public cleanupClosingScene(): void {
|
public cleanupClosingScene(): void {
|
||||||
// stop playing audio, close any open website, stop any open Jitsi
|
// stop playing audio, close any open website, stop any open Jitsi
|
||||||
coWebsiteManager.closeCoWebsites();
|
coWebsiteManager.closeCoWebsites().catch((e) => console.error(e));
|
||||||
// Stop the script, if any
|
// Stop the script, if any
|
||||||
const scripts = this.getScriptUrls(this.mapFile);
|
const scripts = this.getScriptUrls(this.mapFile);
|
||||||
for (const script of scripts) {
|
for (const script of scripts) {
|
||||||
@ -1467,6 +1554,7 @@ ${escapedMessage}
|
|||||||
iframeListener.unregisterAnswerer("openCoWebsite");
|
iframeListener.unregisterAnswerer("openCoWebsite");
|
||||||
iframeListener.unregisterAnswerer("getCoWebsites");
|
iframeListener.unregisterAnswerer("getCoWebsites");
|
||||||
iframeListener.unregisterAnswerer("setPlayerOutline");
|
iframeListener.unregisterAnswerer("setPlayerOutline");
|
||||||
|
iframeListener.unregisterAnswerer("setVariable");
|
||||||
this.sharedVariablesManager?.close();
|
this.sharedVariablesManager?.close();
|
||||||
this.embeddedWebsiteManager?.close();
|
this.embeddedWebsiteManager?.close();
|
||||||
|
|
||||||
@ -1945,6 +2033,7 @@ ${escapedMessage}
|
|||||||
|
|
||||||
this.loader.resize();
|
this.loader.resize();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getObjectLayerData(objectName: string): ITiledMapObject | undefined {
|
private getObjectLayerData(objectName: string): ITiledMapObject | undefined {
|
||||||
for (const layer of this.mapFile.layers) {
|
for (const layer of this.mapFile.layers) {
|
||||||
if (layer.type === "objectgroup" && layer.name === "floorLayer") {
|
if (layer.type === "objectgroup" && layer.name === "floorLayer") {
|
||||||
@ -1957,6 +2046,7 @@ ${escapedMessage}
|
|||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private reposition(): void {
|
private reposition(): void {
|
||||||
// Recompute camera offset if needed
|
// Recompute camera offset if needed
|
||||||
biggestAvailableAreaStore.recompute();
|
biggestAvailableAreaStore.recompute();
|
||||||
@ -1975,7 +2065,9 @@ ${escapedMessage}
|
|||||||
const jitsiUrl = allProps.get(GameMapProperties.JITSI_URL) as string | undefined;
|
const jitsiUrl = allProps.get(GameMapProperties.JITSI_URL) as string | undefined;
|
||||||
const jitsiWidth = allProps.get(GameMapProperties.JITSI_WIDTH) as number | undefined;
|
const jitsiWidth = allProps.get(GameMapProperties.JITSI_WIDTH) as number | undefined;
|
||||||
|
|
||||||
jitsiFactory.start(roomName, this.playerName, jwt, jitsiConfig, jitsiInterfaceConfig, jitsiUrl, jitsiWidth);
|
jitsiFactory
|
||||||
|
.start(roomName, this.playerName, jwt, jitsiConfig, jitsiInterfaceConfig, jitsiUrl, jitsiWidth)
|
||||||
|
.catch((e) => console.error(e));
|
||||||
this.connection?.setSilent(true);
|
this.connection?.setSilent(true);
|
||||||
mediaManager.hideGameOverlay();
|
mediaManager.hideGameOverlay();
|
||||||
analyticsClient.enteredJitsi(roomName, this.room.id);
|
analyticsClient.enteredJitsi(roomName, this.room.id);
|
||||||
|
@ -3,6 +3,7 @@ import { iframeListener } from "../../Api/IframeListener";
|
|||||||
import type { GameMap } from "./GameMap";
|
import type { GameMap } from "./GameMap";
|
||||||
import type { ITiledMapLayer, ITiledMapObject } from "../Map/ITiledMap";
|
import type { ITiledMapLayer, ITiledMapObject } from "../Map/ITiledMap";
|
||||||
import { GameMapProperties } from "./GameMapProperties";
|
import { GameMapProperties } from "./GameMapProperties";
|
||||||
|
import type { SetVariableEvent } from "../../Api/Events/SetVariableEvent";
|
||||||
|
|
||||||
interface Variable {
|
interface Variable {
|
||||||
defaultValue: unknown;
|
defaultValue: unknown;
|
||||||
@ -41,58 +42,58 @@ export class SharedVariablesManager {
|
|||||||
this._variables.set(name, value);
|
this._variables.set(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
roomConnection.onSetVariable((name, value) => {
|
roomConnection.variableMessageStream.subscribe(({ name, value }) => {
|
||||||
this._variables.set(name, value);
|
this._variables.set(name, value);
|
||||||
|
|
||||||
// On server change, let's notify the iframes
|
// On server change, let's notify the iframes
|
||||||
iframeListener.setVariable({
|
iframeListener.setVariable({
|
||||||
key: name,
|
key: name,
|
||||||
value: value,
|
value: value,
|
||||||
|
target: "global",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// When a variable is modified from an iFrame
|
public setVariable(event: SetVariableEvent, source: MessageEventSource | null): void {
|
||||||
iframeListener.registerAnswerer("setVariable", (event, source) => {
|
const key = event.key;
|
||||||
const key = event.key;
|
|
||||||
|
|
||||||
const object = this.variableObjects.get(key);
|
const object = this.variableObjects.get(key);
|
||||||
|
|
||||||
if (object === undefined) {
|
if (object === undefined) {
|
||||||
const errMsg =
|
const errMsg =
|
||||||
'A script is trying to modify variable "' +
|
'A script is trying to modify variable "' +
|
||||||
key +
|
key +
|
||||||
'" but this variable is not defined in the map.' +
|
'" but this variable is not defined in the map.' +
|
||||||
'There should be an object in the map whose name is "' +
|
'There should be an object in the map whose name is "' +
|
||||||
key +
|
key +
|
||||||
'" and whose type is "variable"';
|
'" and whose type is "variable"';
|
||||||
console.error(errMsg);
|
console.error(errMsg);
|
||||||
throw new Error(errMsg);
|
throw new Error(errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object.writableBy && !this.roomConnection.hasTag(object.writableBy)) {
|
if (object.writableBy && !this.roomConnection.hasTag(object.writableBy)) {
|
||||||
const errMsg =
|
const errMsg =
|
||||||
'A script is trying to modify variable "' +
|
'A script is trying to modify variable "' +
|
||||||
key +
|
key +
|
||||||
'" but this variable is only writable for users with tag "' +
|
'" but this variable is only writable for users with tag "' +
|
||||||
object.writableBy +
|
object.writableBy +
|
||||||
'".';
|
'".';
|
||||||
console.error(errMsg);
|
console.error(errMsg);
|
||||||
throw new Error(errMsg);
|
throw new Error(errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's stop any propagation of the value we set is the same as the existing value.
|
// Let's stop any propagation of the value we set is the same as the existing value.
|
||||||
if (JSON.stringify(event.value) === JSON.stringify(this._variables.get(key))) {
|
if (JSON.stringify(event.value) === JSON.stringify(this._variables.get(key))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._variables.set(key, event.value);
|
this._variables.set(key, event.value);
|
||||||
|
|
||||||
// Dispatch to the room connection.
|
// Dispatch to the room connection.
|
||||||
this.roomConnection.emitSetVariableEvent(key, event.value);
|
this.roomConnection.emitSetVariableEvent(key, event.value);
|
||||||
|
|
||||||
// Dispatch to other iframes
|
// Dispatch to other iframes
|
||||||
iframeListener.dispatchVariableToOtherIframes(key, event.value, source);
|
iframeListener.dispatchVariableToOtherIframes(key, event.value, source);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static findVariablesInMap(gameMap: GameMap): Map<string, Variable> {
|
private static findVariablesInMap(gameMap: GameMap): Map<string, Variable> {
|
||||||
|
@ -40,19 +40,21 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
preload() {
|
preload() {
|
||||||
this.loadCustomSceneSelectCharacters().then((bodyResourceDescriptions) => {
|
this.loadCustomSceneSelectCharacters()
|
||||||
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
|
.then((bodyResourceDescriptions) => {
|
||||||
if (
|
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
|
||||||
bodyResourceDescription.level == undefined ||
|
if (
|
||||||
bodyResourceDescription.level < 0 ||
|
bodyResourceDescription.level == undefined ||
|
||||||
bodyResourceDescription.level > 5
|
bodyResourceDescription.level < 0 ||
|
||||||
) {
|
bodyResourceDescription.level > 5
|
||||||
throw "Texture level is null";
|
) {
|
||||||
}
|
throw "Texture level is null";
|
||||||
this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription);
|
}
|
||||||
});
|
this.layers[bodyResourceDescription.level].unshift(bodyResourceDescription);
|
||||||
this.lazyloadingAttempt = true;
|
});
|
||||||
});
|
this.lazyloadingAttempt = true;
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
|
|
||||||
this.layers = loadAllLayers(this.load);
|
this.layers = loadAllLayers(this.load);
|
||||||
this.lazyloadingAttempt = false;
|
this.lazyloadingAttempt = false;
|
||||||
|
@ -41,12 +41,14 @@ export class SelectCharacterScene extends AbstractCharacterScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
preload() {
|
preload() {
|
||||||
this.loadSelectSceneCharacters().then((bodyResourceDescriptions) => {
|
this.loadSelectSceneCharacters()
|
||||||
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
|
.then((bodyResourceDescriptions) => {
|
||||||
this.playerModels.push(bodyResourceDescription);
|
bodyResourceDescriptions.forEach((bodyResourceDescription) => {
|
||||||
});
|
this.playerModels.push(bodyResourceDescription);
|
||||||
this.lazyloadingAttempt = true;
|
});
|
||||||
});
|
this.lazyloadingAttempt = true;
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e));
|
||||||
this.playerModels = loadAllDefaultModels(this.load);
|
this.playerModels = loadAllDefaultModels(this.load);
|
||||||
this.lazyloadingAttempt = false;
|
this.lazyloadingAttempt = false;
|
||||||
|
|
||||||
|
@ -162,6 +162,7 @@ export interface ITiledTileSet {
|
|||||||
|
|
||||||
imageheight: number;
|
imageheight: number;
|
||||||
imagewidth: number;
|
imagewidth: number;
|
||||||
|
columns: number;
|
||||||
margin: number;
|
margin: number;
|
||||||
name: string;
|
name: string;
|
||||||
properties?: ITiledMapProperty[];
|
properties?: ITiledMapProperty[];
|
||||||
|
@ -100,10 +100,6 @@ export class Player extends Character {
|
|||||||
return [xMovement, yMovement];
|
return [xMovement, yMovement];
|
||||||
}
|
}
|
||||||
|
|
||||||
public enableFollowing() {
|
|
||||||
followStateStore.set("active");
|
|
||||||
}
|
|
||||||
|
|
||||||
public moveUser(delta: number): void {
|
public moveUser(delta: number): void {
|
||||||
const activeEvents = this.userInputManager.getEventListForGameTick();
|
const activeEvents = this.userInputManager.getEventListForGameTick();
|
||||||
const state = get(followStateStore);
|
const state = get(followStateStore);
|
||||||
@ -111,8 +107,7 @@ export class Player extends Character {
|
|||||||
|
|
||||||
if (activeEvents.get(UserInputEvent.Follow)) {
|
if (activeEvents.get(UserInputEvent.Follow)) {
|
||||||
if (state === "off" && this.scene.groups.size > 0) {
|
if (state === "off" && this.scene.groups.size > 0) {
|
||||||
followStateStore.set("requesting");
|
this.sendFollowRequest();
|
||||||
followRoleStore.set("leader");
|
|
||||||
} else if (state === "active") {
|
} else if (state === "active") {
|
||||||
followStateStore.set("ending");
|
followStateStore.set("ending");
|
||||||
}
|
}
|
||||||
@ -125,4 +120,15 @@ export class Player extends Character {
|
|||||||
}
|
}
|
||||||
this.inputStep(activeEvents, x, y);
|
this.inputStep(activeEvents, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sendFollowRequest() {
|
||||||
|
this.scene.connection?.emitFollowRequest();
|
||||||
|
followRoleStore.set("leader");
|
||||||
|
followStateStore.set("active");
|
||||||
|
}
|
||||||
|
|
||||||
|
public startFollowing() {
|
||||||
|
followStateStore.set("active");
|
||||||
|
this.scene.connection?.emitFollowConfirmation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,10 @@ export class WaScaleManager {
|
|||||||
height: height * devicePixelRatio,
|
height: height * devicePixelRatio,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (gameSize.width == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.actualZoom = realSize.width / gameSize.width / devicePixelRatio;
|
this.actualZoom = realSize.width / gameSize.width / devicePixelRatio;
|
||||||
|
|
||||||
this.scaleManager.setZoom(realSize.width / gameSize.width / devicePixelRatio);
|
this.scaleManager.setZoom(realSize.width / gameSize.width / devicePixelRatio);
|
||||||
|
@ -58,7 +58,6 @@ export const followUsersStore = createFollowUsersStore();
|
|||||||
export const followUsersColorStore = derived(
|
export const followUsersColorStore = derived(
|
||||||
[followStateStore, followRoleStore, followUsersStore],
|
[followStateStore, followRoleStore, followUsersStore],
|
||||||
([$followStateStore, $followRoleStore, $followUsersStore]) => {
|
([$followStateStore, $followRoleStore, $followUsersStore]) => {
|
||||||
console.log($followStateStore);
|
|
||||||
if ($followStateStore !== "active") {
|
if ($followStateStore !== "active") {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -5,3 +5,5 @@ export const userMovingStore = writable(false);
|
|||||||
export const requestVisitCardsStore = writable<string | null>(null);
|
export const requestVisitCardsStore = writable<string | null>(null);
|
||||||
|
|
||||||
export const userIsAdminStore = writable(false);
|
export const userIsAdminStore = writable(false);
|
||||||
|
|
||||||
|
export const limitMapStore = writable(false);
|
||||||
|
@ -360,32 +360,27 @@ const implementCorrectTrackBehavior = getNavigatorType() === NavigatorType.firef
|
|||||||
/**
|
/**
|
||||||
* Stops the camera from filming
|
* Stops the camera from filming
|
||||||
*/
|
*/
|
||||||
function applyCameraConstraints(currentStream: MediaStream | null, constraints: MediaTrackConstraints | boolean): void {
|
async function applyCameraConstraints(
|
||||||
|
currentStream: MediaStream | null,
|
||||||
|
constraints: MediaTrackConstraints | boolean
|
||||||
|
): Promise<void[]> {
|
||||||
if (!currentStream) {
|
if (!currentStream) {
|
||||||
return;
|
return [];
|
||||||
}
|
|
||||||
for (const track of currentStream.getVideoTracks()) {
|
|
||||||
toggleConstraints(track, constraints).catch((e) =>
|
|
||||||
console.error("Error while setting new camera constraints:", e)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
return Promise.all(currentStream.getVideoTracks().map((track) => toggleConstraints(track, constraints)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the microphone from listening
|
* Stops the microphone from listening
|
||||||
*/
|
*/
|
||||||
function applyMicrophoneConstraints(
|
async function applyMicrophoneConstraints(
|
||||||
currentStream: MediaStream | null,
|
currentStream: MediaStream | null,
|
||||||
constraints: MediaTrackConstraints | boolean
|
constraints: MediaTrackConstraints | boolean
|
||||||
): void {
|
): Promise<void[]> {
|
||||||
if (!currentStream) {
|
if (!currentStream) {
|
||||||
return;
|
return [];
|
||||||
}
|
|
||||||
for (const track of currentStream.getAudioTracks()) {
|
|
||||||
toggleConstraints(track, constraints).catch((e) =>
|
|
||||||
console.error("Error while setting new audio constraints:", e)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
return Promise.all(currentStream.getAudioTracks().map((track) => toggleConstraints(track, constraints)));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleConstraints(track: MediaStreamTrack, constraints: MediaTrackConstraints | boolean): Promise<void> {
|
async function toggleConstraints(track: MediaStreamTrack, constraints: MediaTrackConstraints | boolean): Promise<void> {
|
||||||
@ -477,8 +472,8 @@ export const localStreamStore = derived<Readable<MediaStreamConstraints>, LocalS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyMicrophoneConstraints(currentStream, constraints.audio || false);
|
applyMicrophoneConstraints(currentStream, constraints.audio || false).catch((e) => console.error(e));
|
||||||
applyCameraConstraints(currentStream, constraints.video || false);
|
applyCameraConstraints(currentStream, constraints.video || false).catch((e) => console.error(e));
|
||||||
|
|
||||||
if (implementCorrectTrackBehavior) {
|
if (implementCorrectTrackBehavior) {
|
||||||
//on good navigators like firefox, we can instantiate the stream once and simply disable or enable the tracks as needed
|
//on good navigators like firefox, we can instantiate the stream once and simply disable or enable the tracks as needed
|
||||||
|
4
front/src/Stores/ModalStore.ts
Normal file
4
front/src/Stores/ModalStore.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
|
export const showLimitRoomModalStore = writable(false);
|
||||||
|
export const showShareLinkMapModalStore = writable(false);
|
@ -3,6 +3,7 @@ import type { PlayerInterface } from "../Phaser/Game/PlayerInterface";
|
|||||||
import type { RoomConnection } from "../Connexion/RoomConnection";
|
import type { RoomConnection } from "../Connexion/RoomConnection";
|
||||||
import { getRandomColor } from "../WebRtc/ColorGenerator";
|
import { getRandomColor } from "../WebRtc/ColorGenerator";
|
||||||
import { localUserStore } from "../Connexion/LocalUserStore";
|
import { localUserStore } from "../Connexion/LocalUserStore";
|
||||||
|
import room from "../Api/iframe/room";
|
||||||
|
|
||||||
let idCount = 0;
|
let idCount = 0;
|
||||||
|
|
||||||
@ -19,7 +20,8 @@ function createPlayersStore() {
|
|||||||
connectToRoomConnection: (roomConnection: RoomConnection) => {
|
connectToRoomConnection: (roomConnection: RoomConnection) => {
|
||||||
players = new Map<number, PlayerInterface>();
|
players = new Map<number, PlayerInterface>();
|
||||||
set(players);
|
set(players);
|
||||||
roomConnection.onUserJoins((message) => {
|
// TODO: it would be cool to unsubscribe properly here
|
||||||
|
roomConnection.userJoinedMessageStream.subscribe((message) => {
|
||||||
update((users) => {
|
update((users) => {
|
||||||
users.set(message.userId, {
|
users.set(message.userId, {
|
||||||
userId: message.userId,
|
userId: message.userId,
|
||||||
@ -33,9 +35,9 @@ function createPlayersStore() {
|
|||||||
return users;
|
return users;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
roomConnection.onUserLeft((userId) => {
|
roomConnection.userLeftMessageStream.subscribe((message) => {
|
||||||
update((users) => {
|
update((users) => {
|
||||||
users.delete(userId);
|
users.delete(message.userId);
|
||||||
return users;
|
return users;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -156,7 +156,7 @@ export const screenSharingLocalStreamStore = derived<Readable<MediaStreamConstra
|
|||||||
error: e instanceof Error ? e : new Error("An unknown error happened"),
|
error: e instanceof Error ? e : new Error("An unknown error happened"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})().catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2,8 +2,7 @@ import type { Room } from "../Connexion/Room";
|
|||||||
import { localUserStore } from "../Connexion/LocalUserStore";
|
import { localUserStore } from "../Connexion/LocalUserStore";
|
||||||
|
|
||||||
export enum GameConnexionTypes {
|
export enum GameConnexionTypes {
|
||||||
anonymous = 1,
|
room = 1,
|
||||||
organization,
|
|
||||||
register,
|
register,
|
||||||
empty,
|
empty,
|
||||||
unknown,
|
unknown,
|
||||||
@ -19,10 +18,8 @@ class UrlManager {
|
|||||||
return GameConnexionTypes.login;
|
return GameConnexionTypes.login;
|
||||||
} else if (url === "/jwt") {
|
} else if (url === "/jwt") {
|
||||||
return GameConnexionTypes.jwt;
|
return GameConnexionTypes.jwt;
|
||||||
} else if (url.includes("_/")) {
|
} else if (url.includes("_/") || url.includes("*/") || url.includes("@/")) {
|
||||||
return GameConnexionTypes.anonymous;
|
return GameConnexionTypes.room;
|
||||||
} else if (url.includes("@/")) {
|
|
||||||
return GameConnexionTypes.organization;
|
|
||||||
} else if (url.includes("register/")) {
|
} else if (url.includes("register/")) {
|
||||||
return GameConnexionTypes.register;
|
return GameConnexionTypes.register;
|
||||||
} else if (url === "/") {
|
} else if (url === "/") {
|
||||||
@ -41,7 +38,7 @@ class UrlManager {
|
|||||||
if (window.location.pathname === room.id) return;
|
if (window.location.pathname === room.id) return;
|
||||||
//Set last room visited! (connected or nor, must to be saved in localstorage and cache API)
|
//Set last room visited! (connected or nor, must to be saved in localstorage and cache API)
|
||||||
//use href to keep # value
|
//use href to keep # value
|
||||||
localUserStore.setLastRoomUrl(room.href);
|
localUserStore.setLastRoomUrl(room.href).catch((e) => console.error(e));
|
||||||
const hash = window.location.hash;
|
const hash = window.location.hash;
|
||||||
const search = room.search.toString();
|
const search = room.search.toString();
|
||||||
history.pushState({}, "WorkAdventure", room.id + (search ? "?" + search : "") + hash);
|
history.pushState({}, "WorkAdventure", room.id + (search ? "?" + search : "") + hash);
|
||||||
|
@ -149,7 +149,7 @@ class CoWebsiteManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buttonCloseCoWebsites.blur();
|
buttonCloseCoWebsites.blur();
|
||||||
this.closeCoWebsites();
|
this.closeCoWebsites().catch((e) => console.error(e));
|
||||||
});
|
});
|
||||||
|
|
||||||
const buttonFullScreenFrame = HtmlUtils.getElementByIdOrFail(cowebsiteFullScreenButtonId);
|
const buttonFullScreenFrame = HtmlUtils.getElementByIdOrFail(cowebsiteFullScreenButtonId);
|
||||||
@ -515,70 +515,72 @@ class CoWebsiteManager {
|
|||||||
throw new Error("Too many we");
|
throw new Error("Too many we");
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise.resolve(callback(this.cowebsiteBufferDom)).then((iframe) => {
|
Promise.resolve(callback(this.cowebsiteBufferDom))
|
||||||
iframe?.classList.add("pixel");
|
.then((iframe) => {
|
||||||
|
iframe?.classList.add("pixel");
|
||||||
|
|
||||||
if (!iframe.id) {
|
if (!iframe.id) {
|
||||||
do {
|
do {
|
||||||
iframe.id = "cowebsite-iframe-" + (Math.random() + 1).toString(36).substring(7);
|
iframe.id = "cowebsite-iframe-" + (Math.random() + 1).toString(36).substring(7);
|
||||||
} while (this.getCoWebsiteById(iframe.id));
|
} while (this.getCoWebsiteById(iframe.id));
|
||||||
}
|
|
||||||
|
|
||||||
const onloadPromise = new Promise<void>((resolve) => {
|
|
||||||
iframe.onload = () => resolve();
|
|
||||||
});
|
|
||||||
|
|
||||||
const icon = this.generateCoWebsiteIcon(iframe);
|
|
||||||
|
|
||||||
const coWebsite = {
|
|
||||||
iframe,
|
|
||||||
icon,
|
|
||||||
position: position ?? this.coWebsites.length,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Iframe management on mobile
|
|
||||||
icon.addEventListener("click", () => {
|
|
||||||
if (this.isSmallScreen()) {
|
|
||||||
this.moveRightPreviousCoWebsite(coWebsite, 0);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
this.coWebsites.push(coWebsite);
|
const onloadPromise = new Promise<void>((resolve) => {
|
||||||
this.cowebsiteSubIconsDom.appendChild(icon);
|
iframe.onload = () => resolve();
|
||||||
|
});
|
||||||
|
|
||||||
const onTimeoutPromise = new Promise<void>((resolve) => {
|
const icon = this.generateCoWebsiteIcon(iframe);
|
||||||
setTimeout(() => resolve(), 2000);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.currentOperationPromise = this.currentOperationPromise
|
const coWebsite = {
|
||||||
.then(() => Promise.race([onloadPromise, onTimeoutPromise]))
|
iframe,
|
||||||
.then(() => {
|
icon,
|
||||||
if (coWebsite.position === 0) {
|
position: position ?? this.coWebsites.length,
|
||||||
this.openMain();
|
};
|
||||||
if (widthPercent) {
|
|
||||||
this.widthPercent = widthPercent;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => {
|
// Iframe management on mobile
|
||||||
this.fire();
|
icon.addEventListener("click", () => {
|
||||||
|
if (this.isSmallScreen()) {
|
||||||
|
this.moveRightPreviousCoWebsite(coWebsite, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.coWebsites.push(coWebsite);
|
||||||
|
this.cowebsiteSubIconsDom.appendChild(icon);
|
||||||
|
|
||||||
|
const onTimeoutPromise = new Promise<void>((resolve) => {
|
||||||
|
setTimeout(() => resolve(), 2000);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.currentOperationPromise = this.currentOperationPromise
|
||||||
|
.then(() => Promise.race([onloadPromise, onTimeoutPromise]))
|
||||||
|
.then(() => {
|
||||||
|
if (coWebsite.position === 0) {
|
||||||
|
this.openMain();
|
||||||
|
if (widthPercent) {
|
||||||
|
this.widthPercent = widthPercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.fire();
|
||||||
|
position !== undefined
|
||||||
|
? this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position)
|
||||||
|
: this.moveCoWebsite(coWebsite, coWebsite.position);
|
||||||
|
}, animationTime);
|
||||||
|
} else {
|
||||||
position !== undefined
|
position !== undefined
|
||||||
? this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position)
|
? this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position)
|
||||||
: this.moveCoWebsite(coWebsite, coWebsite.position);
|
: this.moveCoWebsite(coWebsite, coWebsite.position);
|
||||||
}, animationTime);
|
}
|
||||||
} else {
|
|
||||||
position !== undefined
|
|
||||||
? this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position)
|
|
||||||
: this.moveCoWebsite(coWebsite, coWebsite.position);
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolve(coWebsite);
|
return resolve(coWebsite);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error("Error loadCoWebsite => ", err);
|
console.error("Error loadCoWebsite => ", err);
|
||||||
this.removeCoWebsiteFromStack(coWebsite);
|
this.removeCoWebsiteFromStack(coWebsite);
|
||||||
return reject();
|
return reject();
|
||||||
});
|
});
|
||||||
});
|
})
|
||||||
|
.catch((e) => console.error("Error loadCoWebsite >=> ", e));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,17 +605,21 @@ class CoWebsiteManager {
|
|||||||
return this.currentOperationPromise;
|
return this.currentOperationPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeJitsi() {
|
public async closeJitsi() {
|
||||||
const jitsi = this.searchJitsi();
|
const jitsi = this.searchJitsi();
|
||||||
if (jitsi) {
|
if (jitsi) {
|
||||||
this.closeCoWebsite(jitsi);
|
return this.closeCoWebsite(jitsi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeCoWebsites(): Promise<void> {
|
public closeCoWebsites(): Promise<void> {
|
||||||
this.currentOperationPromise = this.currentOperationPromise.then(() => {
|
this.currentOperationPromise = this.currentOperationPromise.then(() => {
|
||||||
|
const promises: Promise<void>[] = [];
|
||||||
this.coWebsites.forEach((coWebsite: CoWebsite) => {
|
this.coWebsites.forEach((coWebsite: CoWebsite) => {
|
||||||
this.closeCoWebsite(coWebsite);
|
promises.push(this.closeCoWebsite(coWebsite));
|
||||||
|
});
|
||||||
|
return Promise.all(promises).then(() => {
|
||||||
|
return;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return this.currentOperationPromise;
|
return this.currentOperationPromise;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { JITSI_URL } from "../Enum/EnvironmentVariable";
|
import { JITSI_URL } from "../Enum/EnvironmentVariable";
|
||||||
import { coWebsiteManager } from "./CoWebsiteManager";
|
import { CoWebsite, coWebsiteManager } from "./CoWebsiteManager";
|
||||||
import { requestedCameraState, requestedMicrophoneState } from "../Stores/MediaStore";
|
import { requestedCameraState, requestedMicrophoneState } from "../Stores/MediaStore";
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
@ -140,8 +140,8 @@ class JitsiFactory {
|
|||||||
interfaceConfig?: object,
|
interfaceConfig?: object,
|
||||||
jitsiUrl?: string,
|
jitsiUrl?: string,
|
||||||
jitsiWidth?: number
|
jitsiWidth?: number
|
||||||
): void {
|
): Promise<CoWebsite> {
|
||||||
coWebsiteManager.addCoWebsite(
|
return coWebsiteManager.addCoWebsite(
|
||||||
async (cowebsiteDiv) => {
|
async (cowebsiteDiv) => {
|
||||||
// Jitsi meet external API maintains some data in local storage
|
// Jitsi meet external API maintains some data in local storage
|
||||||
// which is sent via the appData URL parameter when joining a
|
// which is sent via the appData URL parameter when joining a
|
||||||
@ -200,7 +200,7 @@ class JitsiFactory {
|
|||||||
const jitsiCoWebsite = coWebsiteManager.searchJitsi();
|
const jitsiCoWebsite = coWebsiteManager.searchJitsi();
|
||||||
|
|
||||||
if (jitsiCoWebsite) {
|
if (jitsiCoWebsite) {
|
||||||
coWebsiteManager.closeJitsi();
|
coWebsiteManager.closeJitsi().catch((e) => console.error(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.jitsiApi.removeListener("audioMuteStatusChanged", this.audioCallback);
|
this.jitsiApi.removeListener("audioMuteStatusChanged", this.audioCallback);
|
||||||
|
@ -75,23 +75,25 @@ export class SimplePeer {
|
|||||||
*/
|
*/
|
||||||
private initialise() {
|
private initialise() {
|
||||||
//receive signal by gemer
|
//receive signal by gemer
|
||||||
this.Connection.receiveWebrtcSignal((message: WebRtcSignalReceivedMessageInterface) => {
|
this.Connection.webRtcSignalToClientMessageStream.subscribe((message: WebRtcSignalReceivedMessageInterface) => {
|
||||||
this.receiveWebrtcSignal(message);
|
this.receiveWebrtcSignal(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
//receive signal by gemer
|
//receive signal by gemer
|
||||||
this.Connection.receiveWebrtcScreenSharingSignal((message: WebRtcSignalReceivedMessageInterface) => {
|
this.Connection.webRtcScreenSharingSignalToClientMessageStream.subscribe(
|
||||||
this.receiveWebrtcScreenSharingSignal(message);
|
(message: WebRtcSignalReceivedMessageInterface) => {
|
||||||
});
|
this.receiveWebrtcScreenSharingSignal(message);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
mediaManager.showGameOverlay();
|
mediaManager.showGameOverlay();
|
||||||
|
|
||||||
//receive message start
|
//receive message start
|
||||||
this.Connection.receiveWebrtcStart((message: UserSimplePeerInterface) => {
|
this.Connection.webRtcStartMessageStream.subscribe((message: UserSimplePeerInterface) => {
|
||||||
this.receiveWebrtcStart(message);
|
this.receiveWebrtcStart(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Connection.disconnectMessage((data: WebRtcDisconnectMessageInterface): void => {
|
this.Connection.webRtcDisconnectMessageStream.subscribe((data: WebRtcDisconnectMessageInterface): void => {
|
||||||
this.closeConnection(data.userId);
|
this.closeConnection(data.userId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -9,30 +9,34 @@ import {
|
|||||||
} from "./Api/Events/IframeEvent";
|
} from "./Api/Events/IframeEvent";
|
||||||
import chat from "./Api/iframe/chat";
|
import chat from "./Api/iframe/chat";
|
||||||
import type { IframeCallback } from "./Api/iframe/IframeApiContribution";
|
import type { IframeCallback } from "./Api/iframe/IframeApiContribution";
|
||||||
import nav from "./Api/iframe/nav";
|
import nav, { CoWebsite } from "./Api/iframe/nav";
|
||||||
import controls from "./Api/iframe/controls";
|
import controls from "./Api/iframe/controls";
|
||||||
import ui from "./Api/iframe/ui";
|
import ui from "./Api/iframe/ui";
|
||||||
import sound from "./Api/iframe/sound";
|
import sound from "./Api/iframe/sound";
|
||||||
import room, { setMapURL, setRoomId } from "./Api/iframe/room";
|
import room, { setMapURL, setRoomId } from "./Api/iframe/room";
|
||||||
import state, { initVariables } from "./Api/iframe/state";
|
import { createState } from "./Api/iframe/state";
|
||||||
import player, { setPlayerName, setTags, setUserRoomToken, setUuid } from "./Api/iframe/player";
|
import player, { setPlayerName, setTags, setUserRoomToken, setUuid } 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 { answerPromises, queryWorkadventure } from "./Api/iframe/IframeApiContribution";
|
import { answerPromises, queryWorkadventure } from "./Api/iframe/IframeApiContribution";
|
||||||
|
import camera from "./Api/iframe/camera";
|
||||||
|
|
||||||
|
const globalState = createState("global");
|
||||||
|
|
||||||
// Notify WorkAdventure that we are ready to receive data
|
// Notify WorkAdventure that we are ready to receive data
|
||||||
const initPromise = queryWorkadventure({
|
const initPromise = queryWorkadventure({
|
||||||
type: "getState",
|
type: "getState",
|
||||||
data: undefined,
|
data: undefined,
|
||||||
}).then((state) => {
|
}).then((gameState) => {
|
||||||
setPlayerName(state.nickname);
|
setPlayerName(gameState.nickname);
|
||||||
setRoomId(state.roomId);
|
setRoomId(gameState.roomId);
|
||||||
setMapURL(state.mapUrl);
|
setMapURL(gameState.mapUrl);
|
||||||
setTags(state.tags);
|
setTags(gameState.tags);
|
||||||
setUuid(state.uuid);
|
setUuid(gameState.uuid);
|
||||||
initVariables(state.variables as Map<string, unknown>);
|
globalState.initVariables(gameState.variables as Map<string, unknown>);
|
||||||
setUserRoomToken(state.userRoomToken);
|
player.state.initVariables(gameState.playerVariables as Map<string, unknown>);
|
||||||
|
setUserRoomToken(gameState.userRoomToken);
|
||||||
});
|
});
|
||||||
|
|
||||||
const wa = {
|
const wa = {
|
||||||
@ -43,7 +47,8 @@ const wa = {
|
|||||||
sound,
|
sound,
|
||||||
room,
|
room,
|
||||||
player,
|
player,
|
||||||
state,
|
camera,
|
||||||
|
state: globalState,
|
||||||
|
|
||||||
onInit(): Promise<void> {
|
onInit(): Promise<void> {
|
||||||
return initPromise;
|
return initPromise;
|
||||||
@ -131,17 +136,17 @@ const wa = {
|
|||||||
/**
|
/**
|
||||||
* @deprecated Use WA.nav.openCoWebSite instead
|
* @deprecated Use WA.nav.openCoWebSite instead
|
||||||
*/
|
*/
|
||||||
openCoWebSite(url: string, allowApi: boolean = false, allowPolicy: string = ""): void {
|
openCoWebSite(url: string, allowApi: boolean = false, allowPolicy: string = ""): Promise<CoWebsite> {
|
||||||
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, allowApi, allowPolicy);
|
return nav.openCoWebSite(url, allowApi, allowPolicy);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use WA.nav.closeCoWebSite instead
|
* @deprecated Use WA.nav.closeCoWebSite instead
|
||||||
*/
|
*/
|
||||||
closeCoWebSite(): void {
|
closeCoWebSite(): Promise<void> {
|
||||||
console.warn("Method WA.closeCoWebSite is deprecated. Please use WA.nav.closeCoWebSite instead");
|
console.warn("Method WA.closeCoWebSite is deprecated. Please use WA.nav.closeCoWebSite instead");
|
||||||
nav.closeCoWebSite();
|
return nav.closeCoWebSite();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -225,7 +230,5 @@ window.addEventListener(
|
|||||||
callback?.callback(payloadData);
|
callback?.callback(payloadData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ...
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1066,6 +1066,7 @@ div.action.danger p.action-body{
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
& > div {
|
& > div {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
import "jasmine";
|
import "jasmine";
|
||||||
import {PlayerMovement} from "../../../src/Phaser/Game/PlayerMovement";
|
import { PlayerMovement } from "../../../src/Phaser/Game/PlayerMovement";
|
||||||
|
|
||||||
describe("Interpolation / Extrapolation", () => {
|
describe("Interpolation / Extrapolation", () => {
|
||||||
it("should interpolate", () => {
|
it("should interpolate", () => {
|
||||||
const playerMovement = new PlayerMovement({
|
const playerMovement = new PlayerMovement(
|
||||||
x: 100, y: 200
|
{
|
||||||
}, 42000,
|
x: 100,
|
||||||
|
y: 200,
|
||||||
|
},
|
||||||
|
42000,
|
||||||
{
|
{
|
||||||
x: 200,
|
x: 200,
|
||||||
y: 100,
|
y: 100,
|
||||||
oldX: 100,
|
oldX: 100,
|
||||||
oldY: 200,
|
oldY: 200,
|
||||||
moving: true,
|
moving: true,
|
||||||
direction: "up"
|
direction: "up",
|
||||||
},
|
},
|
||||||
42200
|
42200
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
expect(playerMovement.isOutdated(42100)).toBe(false);
|
expect(playerMovement.isOutdated(42100)).toBe(false);
|
||||||
expect(playerMovement.isOutdated(43000)).toBe(true);
|
expect(playerMovement.isOutdated(43000)).toBe(true);
|
||||||
@ -26,8 +28,8 @@ describe("Interpolation / Extrapolation", () => {
|
|||||||
y: 150,
|
y: 150,
|
||||||
oldX: 100,
|
oldX: 100,
|
||||||
oldY: 200,
|
oldY: 200,
|
||||||
direction: 'up',
|
direction: "up",
|
||||||
moving: true
|
moving: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(playerMovement.getPosition(42200)).toEqual({
|
expect(playerMovement.getPosition(42200)).toEqual({
|
||||||
@ -35,8 +37,8 @@ describe("Interpolation / Extrapolation", () => {
|
|||||||
y: 100,
|
y: 100,
|
||||||
oldX: 100,
|
oldX: 100,
|
||||||
oldY: 200,
|
oldY: 200,
|
||||||
direction: 'up',
|
direction: "up",
|
||||||
moving: true
|
moving: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(playerMovement.getPosition(42300)).toEqual({
|
expect(playerMovement.getPosition(42300)).toEqual({
|
||||||
@ -44,22 +46,25 @@ describe("Interpolation / Extrapolation", () => {
|
|||||||
y: 50,
|
y: 50,
|
||||||
oldX: 100,
|
oldX: 100,
|
||||||
oldY: 200,
|
oldY: 200,
|
||||||
direction: 'up',
|
direction: "up",
|
||||||
moving: true
|
moving: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not extrapolate if we stop", () => {
|
it("should not extrapolate if we stop", () => {
|
||||||
const playerMovement = new PlayerMovement({
|
const playerMovement = new PlayerMovement(
|
||||||
x: 100, y: 200
|
{
|
||||||
}, 42000,
|
x: 100,
|
||||||
|
y: 200,
|
||||||
|
},
|
||||||
|
42000,
|
||||||
{
|
{
|
||||||
x: 200,
|
x: 200,
|
||||||
y: 100,
|
y: 100,
|
||||||
oldX: 100,
|
oldX: 100,
|
||||||
oldY: 200,
|
oldY: 200,
|
||||||
moving: false,
|
moving: false,
|
||||||
direction: "up"
|
direction: "up",
|
||||||
},
|
},
|
||||||
42200
|
42200
|
||||||
);
|
);
|
||||||
@ -69,22 +74,25 @@ describe("Interpolation / Extrapolation", () => {
|
|||||||
y: 100,
|
y: 100,
|
||||||
oldX: 100,
|
oldX: 100,
|
||||||
oldY: 200,
|
oldY: 200,
|
||||||
direction: 'up',
|
direction: "up",
|
||||||
moving: false
|
moving: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should keep moving until it stops", () => {
|
it("should keep moving until it stops", () => {
|
||||||
const playerMovement = new PlayerMovement({
|
const playerMovement = new PlayerMovement(
|
||||||
x: 100, y: 200
|
{
|
||||||
}, 42000,
|
x: 100,
|
||||||
|
y: 200,
|
||||||
|
},
|
||||||
|
42000,
|
||||||
{
|
{
|
||||||
x: 200,
|
x: 200,
|
||||||
y: 100,
|
y: 100,
|
||||||
oldX: 100,
|
oldX: 100,
|
||||||
oldY: 200,
|
oldY: 200,
|
||||||
moving: false,
|
moving: false,
|
||||||
direction: "up"
|
direction: "up",
|
||||||
},
|
},
|
||||||
42200
|
42200
|
||||||
);
|
);
|
||||||
@ -94,8 +102,8 @@ describe("Interpolation / Extrapolation", () => {
|
|||||||
y: 150,
|
y: 150,
|
||||||
oldX: 100,
|
oldX: 100,
|
||||||
oldY: 200,
|
oldY: 200,
|
||||||
direction: 'up',
|
direction: "up",
|
||||||
moving: false
|
moving: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
143
front/yarn.lock
143
front/yarn.lock
@ -150,6 +150,59 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353"
|
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353"
|
||||||
integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==
|
integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==
|
||||||
|
|
||||||
|
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
|
||||||
|
integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78=
|
||||||
|
|
||||||
|
"@protobufjs/base64@^1.1.2":
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735"
|
||||||
|
integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
|
||||||
|
|
||||||
|
"@protobufjs/codegen@^2.0.4":
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb"
|
||||||
|
integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
|
||||||
|
|
||||||
|
"@protobufjs/eventemitter@^1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70"
|
||||||
|
integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A=
|
||||||
|
|
||||||
|
"@protobufjs/fetch@^1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45"
|
||||||
|
integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=
|
||||||
|
dependencies:
|
||||||
|
"@protobufjs/aspromise" "^1.1.1"
|
||||||
|
"@protobufjs/inquire" "^1.1.0"
|
||||||
|
|
||||||
|
"@protobufjs/float@^1.0.2":
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1"
|
||||||
|
integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=
|
||||||
|
|
||||||
|
"@protobufjs/inquire@^1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089"
|
||||||
|
integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=
|
||||||
|
|
||||||
|
"@protobufjs/path@^1.1.2":
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d"
|
||||||
|
integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=
|
||||||
|
|
||||||
|
"@protobufjs/pool@^1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54"
|
||||||
|
integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=
|
||||||
|
|
||||||
|
"@protobufjs/utf8@^1.1.0":
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
|
||||||
|
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
|
||||||
|
|
||||||
"@sentry/types@^6.11.0":
|
"@sentry/types@^6.11.0":
|
||||||
version "6.12.0"
|
version "6.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.12.0.tgz#b7395688a79403c6df8d8bb8d81deb8222519853"
|
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.12.0.tgz#b7395688a79403c6df8d8bb8d81deb8222519853"
|
||||||
@ -293,6 +346,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||||
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
||||||
|
|
||||||
|
"@types/long@^4.0.1":
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
|
||||||
|
integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
|
||||||
|
|
||||||
"@types/mime@^1":
|
"@types/mime@^1":
|
||||||
version "1.3.2"
|
version "1.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
|
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
|
||||||
@ -317,11 +375,26 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-15.3.0.tgz#d6fed7d6bc6854306da3dea1af9f874b00783e26"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-15.3.0.tgz#d6fed7d6bc6854306da3dea1af9f874b00783e26"
|
||||||
integrity sha512-8/bnjSZD86ZfpBsDlCIkNXIvm+h6wi9g7IqL+kmFkQ+Wvu3JrasgLElfiPgoo8V8vVfnEi0QVS12gbl94h9YsQ==
|
integrity sha512-8/bnjSZD86ZfpBsDlCIkNXIvm+h6wi9g7IqL+kmFkQ+Wvu3JrasgLElfiPgoo8V8vVfnEi0QVS12gbl94h9YsQ==
|
||||||
|
|
||||||
|
"@types/node@>=13.7.0":
|
||||||
|
version "17.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.5.tgz#57ca67ec4e57ad9e4ef5a6bab48a15387a1c83e0"
|
||||||
|
integrity sha512-w3mrvNXLeDYV1GKTZorGJQivK6XLCoGwpnyJFbJVK/aTBQUxOCaa/GlFAAN3OTDFcb7h5tiFG+YXCO2By+riZw==
|
||||||
|
|
||||||
|
"@types/object-hash@^1.3.0":
|
||||||
|
version "1.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/object-hash/-/object-hash-1.3.4.tgz#079ba142be65833293673254831b5e3e847fe58b"
|
||||||
|
integrity sha512-xFdpkAkikBgqBdG9vIlsqffDV8GpvnPEzs0IUtr1v3BEB97ijsFQ4RXVbUZwjFThhB4MDSTUfvmxUD5PGx0wXA==
|
||||||
|
|
||||||
"@types/parse-json@^4.0.0":
|
"@types/parse-json@^4.0.0":
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
||||||
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
|
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
|
||||||
|
|
||||||
|
"@types/prettier@^1.19.0":
|
||||||
|
version "1.19.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f"
|
||||||
|
integrity sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ==
|
||||||
|
|
||||||
"@types/pug@^2.0.4":
|
"@types/pug@^2.0.4":
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/pug/-/pug-2.0.4.tgz#8772fcd0418e3cd2cc171555d73007415051f4b2"
|
resolved "https://registry.yarnpkg.com/@types/pug/-/pug-2.0.4.tgz#8772fcd0418e3cd2cc171555d73007415051f4b2"
|
||||||
@ -1656,6 +1729,11 @@ cssesc@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
||||||
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
|
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
|
||||||
|
|
||||||
|
dataloader@^1.4.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-1.4.0.tgz#bca11d867f5d3f1b9ed9f737bd15970c65dff5c8"
|
||||||
|
integrity sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==
|
||||||
|
|
||||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
|
debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||||
@ -3662,7 +3740,7 @@ lodash.merge@^4.6.2:
|
|||||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||||
|
|
||||||
lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.20:
|
lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20:
|
||||||
version "4.17.21"
|
version "4.17.21"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
@ -3695,6 +3773,11 @@ lokijs@^1.5.12:
|
|||||||
resolved "https://registry.yarnpkg.com/lokijs/-/lokijs-1.5.12.tgz#cb55b37009bdf09ee7952a6adddd555b893653a0"
|
resolved "https://registry.yarnpkg.com/lokijs/-/lokijs-1.5.12.tgz#cb55b37009bdf09ee7952a6adddd555b893653a0"
|
||||||
integrity sha512-Q5ALD6JiS6xAUWCwX3taQmgwxyveCtIIuL08+ml0nHwT3k0S/GIFJN+Hd38b1qYIMaE5X++iqsqWVksz7SYW+Q==
|
integrity sha512-Q5ALD6JiS6xAUWCwX3taQmgwxyveCtIIuL08+ml0nHwT3k0S/GIFJN+Hd38b1qYIMaE5X++iqsqWVksz7SYW+Q==
|
||||||
|
|
||||||
|
long@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
|
||||||
|
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
|
||||||
|
|
||||||
lower-case@^2.0.2:
|
lower-case@^2.0.2:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
|
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
|
||||||
@ -4098,6 +4181,11 @@ object-copy@^0.1.0:
|
|||||||
define-property "^0.2.5"
|
define-property "^0.2.5"
|
||||||
kind-of "^3.0.3"
|
kind-of "^3.0.3"
|
||||||
|
|
||||||
|
object-hash@^1.3.1:
|
||||||
|
version "1.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df"
|
||||||
|
integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==
|
||||||
|
|
||||||
object-inspect@^1.9.0:
|
object-inspect@^1.9.0:
|
||||||
version "1.10.3"
|
version "1.10.3"
|
||||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369"
|
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369"
|
||||||
@ -4590,6 +4678,11 @@ prettier-plugin-svelte@^2.5.0:
|
|||||||
resolved "https://registry.yarnpkg.com/prettier-plugin-svelte/-/prettier-plugin-svelte-2.5.0.tgz#7922534729f7febe59b4c56c3f5360539f0d8ab1"
|
resolved "https://registry.yarnpkg.com/prettier-plugin-svelte/-/prettier-plugin-svelte-2.5.0.tgz#7922534729f7febe59b4c56c3f5360539f0d8ab1"
|
||||||
integrity sha512-+iHY2uGChOngrgKielJUnqo74gIL/EO5oeWm8MftFWjEi213lq9QYTOwm1pv4lI1nA61tdgf80CF2i5zMcu1kw==
|
integrity sha512-+iHY2uGChOngrgKielJUnqo74gIL/EO5oeWm8MftFWjEi213lq9QYTOwm1pv4lI1nA61tdgf80CF2i5zMcu1kw==
|
||||||
|
|
||||||
|
prettier@^2.0.2:
|
||||||
|
version "2.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a"
|
||||||
|
integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==
|
||||||
|
|
||||||
prettier@^2.3.1:
|
prettier@^2.3.1:
|
||||||
version "2.3.1"
|
version "2.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.1.tgz#76903c3f8c4449bc9ac597acefa24dc5ad4cbea6"
|
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.1.tgz#76903c3f8c4449bc9ac597acefa24dc5ad4cbea6"
|
||||||
@ -4618,6 +4711,25 @@ progress@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||||
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
|
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
|
||||||
|
|
||||||
|
protobufjs@^6.8.8:
|
||||||
|
version "6.11.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b"
|
||||||
|
integrity sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==
|
||||||
|
dependencies:
|
||||||
|
"@protobufjs/aspromise" "^1.1.2"
|
||||||
|
"@protobufjs/base64" "^1.1.2"
|
||||||
|
"@protobufjs/codegen" "^2.0.4"
|
||||||
|
"@protobufjs/eventemitter" "^1.1.0"
|
||||||
|
"@protobufjs/fetch" "^1.1.0"
|
||||||
|
"@protobufjs/float" "^1.0.2"
|
||||||
|
"@protobufjs/inquire" "^1.1.0"
|
||||||
|
"@protobufjs/path" "^1.1.2"
|
||||||
|
"@protobufjs/pool" "^1.1.0"
|
||||||
|
"@protobufjs/utf8" "^1.1.0"
|
||||||
|
"@types/long" "^4.0.1"
|
||||||
|
"@types/node" ">=13.7.0"
|
||||||
|
long "^4.0.0"
|
||||||
|
|
||||||
proxy-addr@~2.0.5:
|
proxy-addr@~2.0.5:
|
||||||
version "2.0.6"
|
version "2.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
|
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
|
||||||
@ -5819,6 +5931,35 @@ ts-node@^10.4.0:
|
|||||||
make-error "^1.1.1"
|
make-error "^1.1.1"
|
||||||
yn "3.1.1"
|
yn "3.1.1"
|
||||||
|
|
||||||
|
ts-poet@^4.5.0:
|
||||||
|
version "4.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-poet/-/ts-poet-4.6.1.tgz#015dc823d726655af9f095c900f84ed7c60e2dd3"
|
||||||
|
integrity sha512-DXJ+mBJIDp+jiaUgB4N5I/sczHHDU2FWacdbDNVAVS4Mh4hb7ckpvUWVW7m7/nAOcjR0r4Wt+7AoO7FeJKExfA==
|
||||||
|
dependencies:
|
||||||
|
"@types/prettier" "^1.19.0"
|
||||||
|
lodash "^4.17.15"
|
||||||
|
prettier "^2.0.2"
|
||||||
|
|
||||||
|
ts-proto-descriptors@^1.2.1:
|
||||||
|
version "1.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-proto-descriptors/-/ts-proto-descriptors-1.3.1.tgz#760ebaaa19475b03662f7b358ffea45b9c5348f5"
|
||||||
|
integrity sha512-Cybb3fqceMwA6JzHdC32dIo8eVGVmXrM6TWhdk1XQVVHT/6OQqk0ioyX1dIdu3rCIBhRmWUhUE4HsyK+olmgMw==
|
||||||
|
dependencies:
|
||||||
|
long "^4.0.0"
|
||||||
|
protobufjs "^6.8.8"
|
||||||
|
|
||||||
|
ts-proto@^1.96.0:
|
||||||
|
version "1.96.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-proto/-/ts-proto-1.96.0.tgz#63768d7da533b337aee84db065dd66773bd4cac9"
|
||||||
|
integrity sha512-fKwaGzi8EOCU9xwmcXK917jj1WhFdLbFkPRawQ+5CAZM9eSXr/mpkz/yEctXCiuei364z6jAB2Odb64KCDFTPQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/object-hash" "^1.3.0"
|
||||||
|
dataloader "^1.4.0"
|
||||||
|
object-hash "^1.3.1"
|
||||||
|
protobufjs "^6.8.8"
|
||||||
|
ts-poet "^4.5.0"
|
||||||
|
ts-proto-descriptors "^1.2.1"
|
||||||
|
|
||||||
tsconfig-paths@^3.9.0:
|
tsconfig-paths@^3.9.0:
|
||||||
version "3.9.0"
|
version "3.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b"
|
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b"
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
const heightField = document.getElementById('height');
|
const heightField = document.getElementById('height');
|
||||||
const urlField = document.getElementById('url');
|
const urlField = document.getElementById('url');
|
||||||
const visibleField = document.getElementById('visible');
|
const visibleField = document.getElementById('visible');
|
||||||
|
const originField = document.getElementById('origin');
|
||||||
|
const scaleField = document.getElementById('scale');
|
||||||
|
|
||||||
createButton.addEventListener('click', () => {
|
createButton.addEventListener('click', () => {
|
||||||
console.log('CREATING NEW EMBEDDED IFRAME');
|
console.log('CREATING NEW EMBEDDED IFRAME');
|
||||||
@ -28,6 +30,8 @@
|
|||||||
height: parseInt(heightField.value),
|
height: parseInt(heightField.value),
|
||||||
},
|
},
|
||||||
visible: !!visibleField.value,
|
visible: !!visibleField.value,
|
||||||
|
origin: originField.value,
|
||||||
|
scale: parseFloat(scaleField.value),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -61,6 +65,16 @@
|
|||||||
const website = await WA.room.website.get('test');
|
const website = await WA.room.website.get('test');
|
||||||
website.visible = this.checked;
|
website.visible = this.checked;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
originField.addEventListener('change', async function() {
|
||||||
|
const website = await WA.room.website.get('test');
|
||||||
|
website.origin = this.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
scaleField.addEventListener('change', async function() {
|
||||||
|
const website = await WA.room.website.get('test');
|
||||||
|
website.scale = parseFloat(this.value);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@ -72,6 +86,8 @@ width: <input type="text" id="width" value="600" /><br/>
|
|||||||
height: <input type="text" id="height" value="400" /><br/>
|
height: <input type="text" id="height" value="400" /><br/>
|
||||||
URL: <input type="text" id="url" value="https://mensuel.framapad.org/p/rt6c904745-9oxm?lang=en" /><br/>
|
URL: <input type="text" id="url" value="https://mensuel.framapad.org/p/rt6c904745-9oxm?lang=en" /><br/>
|
||||||
Visible: <input type="checkbox" id="visible" value=1 /><br/>
|
Visible: <input type="checkbox" id="visible" value=1 /><br/>
|
||||||
|
Origin: <input type="text" id="origin" value="map" /><br/>
|
||||||
|
Scale: <input type="text" id="scale" value=1 /><br/>
|
||||||
|
|
||||||
<button id="createEmbeddedWebsite">Create embedded website</button>
|
<button id="createEmbeddedWebsite">Create embedded website</button>
|
||||||
|
|
||||||
|
@ -20,6 +20,10 @@ export const isMapDetailsData = new tg.IsInterface()
|
|||||||
})
|
})
|
||||||
.withOptionalProperties({
|
.withOptionalProperties({
|
||||||
iframeAuthentication: tg.isNullable(tg.isString),
|
iframeAuthentication: tg.isNullable(tg.isString),
|
||||||
|
// The date (in ISO 8601 format) at which the room will expire
|
||||||
|
expireOn: tg.isString,
|
||||||
|
// Whether the "report" feature is enabled or not on this room
|
||||||
|
canReport: tg.isBoolean,
|
||||||
})
|
})
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
|
@ -4,13 +4,14 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"proto": "grpc_tools_node_protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --grpc_out=generated --js_out=\"import_style=commonjs,binary:generated\" --ts_out=generated -I ./protos protos/*.proto",
|
"proto": "grpc_tools_node_protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --grpc_out=generated --js_out=\"import_style=commonjs,binary:generated\" --ts_out=generated -I ./protos protos/*.proto",
|
||||||
|
"ts-proto": "grpc_tools_node_protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=ts-proto-generated --ts_proto_opt=oneof=unions --ts_proto_opt=esModuleInterop=true protos/*.proto",
|
||||||
"copy-to-back": "rm -rf ../back/src/Messages/generated && cp -rf generated/ ../back/src/Messages/generated",
|
"copy-to-back": "rm -rf ../back/src/Messages/generated && cp -rf generated/ ../back/src/Messages/generated",
|
||||||
"copy-to-front": "rm -rf ../front/src/Messages/generated && cp -rf generated/ ../front/src/Messages/generated",
|
"copy-to-front-ts-proto": "sed 's/import { Observable } from \"rxjs\";/import type { Observable } from \"rxjs\";/g' ts-proto-generated/protos/messages.ts > ../front/src/Messages/ts-proto-generated/messages.ts",
|
||||||
"copy-to-pusher": "rm -rf ../pusher/src/Messages/generated && cp -rf generated/ ../pusher/src/Messages/generated",
|
"copy-to-pusher": "rm -rf ../pusher/src/Messages/generated && cp -rf generated/ ../pusher/src/Messages/generated",
|
||||||
"json-copy-to-pusher": "rm -rf ../pusher/src/Messages/JsonMessages/* && cp -rf JsonMessages/* ../pusher/src/Messages/JsonMessages/",
|
"json-copy-to-pusher": "rm -rf ../pusher/src/Messages/JsonMessages/* && cp -rf JsonMessages/* ../pusher/src/Messages/JsonMessages/",
|
||||||
"json-copy-to-front": "rm -rf ../front/src/Messages/JsonMessages/* && cp -rf JsonMessages/* ../front/src/Messages/JsonMessages/",
|
"json-copy-to-front": "rm -rf ../front/src/Messages/JsonMessages/* && cp -rf JsonMessages/* ../front/src/Messages/JsonMessages/",
|
||||||
"precommit": "lint-staged",
|
"precommit": "lint-staged",
|
||||||
"proto-all": "yarn run proto && yarn run copy-to-back && yarn run copy-to-front && yarn run copy-to-pusher && yarn run json-copy-to-pusher && yarn run json-copy-to-front",
|
"proto-all": "yarn run proto && yarn run ts-proto && yarn run copy-to-back && yarn run copy-to-front-ts-proto && yarn run copy-to-pusher && yarn run json-copy-to-pusher && yarn run json-copy-to-front",
|
||||||
"proto:watch": "yarn run proto-all; inotifywait -q -m -e close_write protos/messages.proto JsonMessages/ | while read -r filename event; do yarn run proto-all; done",
|
"proto:watch": "yarn run proto-all; inotifywait -q -m -e close_write protos/messages.proto JsonMessages/ | while read -r filename event; do yarn run proto-all; done",
|
||||||
"pretty": "yarn prettier --write 'JsonMessages/**/*.ts'",
|
"pretty": "yarn prettier --write 'JsonMessages/**/*.ts'",
|
||||||
"pretty-check": "yarn prettier --check 'JsonMessages/**/*.ts'"
|
"pretty-check": "yarn prettier --check 'JsonMessages/**/*.ts'"
|
||||||
@ -18,7 +19,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"generic-type-guard": "^3.5.0",
|
"generic-type-guard": "^3.5.0",
|
||||||
"google-protobuf": "^3.13.0",
|
"google-protobuf": "^3.13.0",
|
||||||
"grpc": "^1.24.4"
|
"grpc": "^1.24.4",
|
||||||
|
"ts-proto": "^1.96.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/google-protobuf": "^3.7.4",
|
"@types/google-protobuf": "^3.7.4",
|
||||||
|
@ -296,8 +296,6 @@ message ServerToClientMessage {
|
|||||||
WebRtcSignalToClientMessage webRtcSignalToClientMessage = 5;
|
WebRtcSignalToClientMessage webRtcSignalToClientMessage = 5;
|
||||||
WebRtcSignalToClientMessage webRtcScreenSharingSignalToClientMessage = 6;
|
WebRtcSignalToClientMessage webRtcScreenSharingSignalToClientMessage = 6;
|
||||||
WebRtcDisconnectMessage webRtcDisconnectMessage = 7;
|
WebRtcDisconnectMessage webRtcDisconnectMessage = 7;
|
||||||
PlayGlobalMessage playGlobalMessage = 8;
|
|
||||||
StopGlobalMessage stopGlobalMessage = 9;
|
|
||||||
TeleportMessageMessage teleportMessageMessage = 10;
|
TeleportMessageMessage teleportMessageMessage = 10;
|
||||||
SendJitsiJwtMessage sendJitsiJwtMessage = 11;
|
SendJitsiJwtMessage sendJitsiJwtMessage = 11;
|
||||||
SendUserMessage sendUserMessage = 12;
|
SendUserMessage sendUserMessage = 12;
|
||||||
@ -390,8 +388,6 @@ message PusherToBackMessage {
|
|||||||
SetPlayerDetailsMessage setPlayerDetailsMessage = 5;
|
SetPlayerDetailsMessage setPlayerDetailsMessage = 5;
|
||||||
WebRtcSignalToServerMessage webRtcSignalToServerMessage = 6;
|
WebRtcSignalToServerMessage webRtcSignalToServerMessage = 6;
|
||||||
WebRtcSignalToServerMessage webRtcScreenSharingSignalToServerMessage = 7;
|
WebRtcSignalToServerMessage webRtcScreenSharingSignalToServerMessage = 7;
|
||||||
PlayGlobalMessage playGlobalMessage = 8;
|
|
||||||
StopGlobalMessage stopGlobalMessage = 9;
|
|
||||||
ReportPlayerMessage reportPlayerMessage = 10;
|
ReportPlayerMessage reportPlayerMessage = 10;
|
||||||
QueryJitsiJwtMessage queryJitsiJwtMessage = 11;
|
QueryJitsiJwtMessage queryJitsiJwtMessage = 11;
|
||||||
SendUserMessage sendUserMessage = 12;
|
SendUserMessage sendUserMessage = 12;
|
||||||
|
2
messages/ts-proto-generated/.gitignore
vendored
Normal file
2
messages/ts-proto-generated/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
@ -174,6 +174,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.7.tgz#8ea1e8f8eae2430cf440564b98c6dfce1ec5945d"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.7.tgz#8ea1e8f8eae2430cf440564b98c6dfce1ec5945d"
|
||||||
integrity sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==
|
integrity sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==
|
||||||
|
|
||||||
|
"@types/node@>=13.7.0":
|
||||||
|
version "17.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.5.tgz#57ca67ec4e57ad9e4ef5a6bab48a15387a1c83e0"
|
||||||
|
integrity sha512-w3mrvNXLeDYV1GKTZorGJQivK6XLCoGwpnyJFbJVK/aTBQUxOCaa/GlFAAN3OTDFcb7h5tiFG+YXCO2By+riZw==
|
||||||
|
|
||||||
"@types/node@^12.12.29":
|
"@types/node@^12.12.29":
|
||||||
version "12.19.4"
|
version "12.19.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.4.tgz#cdfbb62e26c7435ed9aab9c941393cc3598e9b46"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.4.tgz#cdfbb62e26c7435ed9aab9c941393cc3598e9b46"
|
||||||
@ -184,6 +189,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.30.tgz#1ed6e01e4ca576d5aec9cc802cc3bcf94c274192"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.30.tgz#1ed6e01e4ca576d5aec9cc802cc3bcf94c274192"
|
||||||
integrity sha512-HmqFpNzp3TSELxU/bUuRK+xzarVOAsR00hzcvM0TXrMlt/+wcSLa5q6YhTb6/cA6wqDCZLDcfd8fSL95x5h7AA==
|
integrity sha512-HmqFpNzp3TSELxU/bUuRK+xzarVOAsR00hzcvM0TXrMlt/+wcSLa5q6YhTb6/cA6wqDCZLDcfd8fSL95x5h7AA==
|
||||||
|
|
||||||
|
"@types/object-hash@^1.3.0":
|
||||||
|
version "1.3.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/object-hash/-/object-hash-1.3.4.tgz#079ba142be65833293673254831b5e3e847fe58b"
|
||||||
|
integrity sha512-xFdpkAkikBgqBdG9vIlsqffDV8GpvnPEzs0IUtr1v3BEB97ijsFQ4RXVbUZwjFThhB4MDSTUfvmxUD5PGx0wXA==
|
||||||
|
|
||||||
"@types/parse-json@^4.0.0":
|
"@types/parse-json@^4.0.0":
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
||||||
@ -194,6 +204,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/parsimmon/-/parsimmon-1.10.4.tgz#7639e16015440d9baf622f83c12dae47787226b7"
|
resolved "https://registry.yarnpkg.com/@types/parsimmon/-/parsimmon-1.10.4.tgz#7639e16015440d9baf622f83c12dae47787226b7"
|
||||||
integrity sha512-M56NfQHfaWuaj6daSgCVs7jh8fXLI3LmxjRoQxmOvYesgIkI+9HPsDLO0vd7wX7cwA0D0ZWFEJdp0VPwLdS+bQ==
|
integrity sha512-M56NfQHfaWuaj6daSgCVs7jh8fXLI3LmxjRoQxmOvYesgIkI+9HPsDLO0vd7wX7cwA0D0ZWFEJdp0VPwLdS+bQ==
|
||||||
|
|
||||||
|
"@types/prettier@^1.19.0":
|
||||||
|
version "1.19.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f"
|
||||||
|
integrity sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ==
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin@^4.7.0":
|
"@typescript-eslint/eslint-plugin@^4.7.0":
|
||||||
version "4.7.0"
|
version "4.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.7.0.tgz#85c9bbda00c0cb604d3c241f7bc7fb171a2d3479"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.7.0.tgz#85c9bbda00c0cb604d3c241f7bc7fb171a2d3479"
|
||||||
@ -1156,6 +1171,11 @@ dashdash@^1.12.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "^1.0.0"
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
|
dataloader@^1.4.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-1.4.0.tgz#bca11d867f5d3f1b9ed9f737bd15970c65dff5c8"
|
||||||
|
integrity sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==
|
||||||
|
|
||||||
date.js@^0.3.1:
|
date.js@^0.3.1:
|
||||||
version "0.3.3"
|
version "0.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/date.js/-/date.js-0.3.3.tgz#ef1e92332f507a638795dbb985e951882e50bbda"
|
resolved "https://registry.yarnpkg.com/date.js/-/date.js-0.3.3.tgz#ef1e92332f507a638795dbb985e951882e50bbda"
|
||||||
@ -3154,6 +3174,11 @@ object-copy@^0.1.0:
|
|||||||
define-property "^0.2.5"
|
define-property "^0.2.5"
|
||||||
kind-of "^3.0.3"
|
kind-of "^3.0.3"
|
||||||
|
|
||||||
|
object-hash@^1.3.1:
|
||||||
|
version "1.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df"
|
||||||
|
integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==
|
||||||
|
|
||||||
object-inspect@^1.8.0:
|
object-inspect@^1.8.0:
|
||||||
version "1.8.0"
|
version "1.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
|
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
|
||||||
@ -3423,7 +3448,7 @@ prelude-ls@^1.2.1:
|
|||||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
||||||
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
|
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
|
||||||
|
|
||||||
prettier@^2.3.1:
|
prettier@^2.0.2, prettier@^2.3.1:
|
||||||
version "2.5.1"
|
version "2.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a"
|
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a"
|
||||||
integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==
|
integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==
|
||||||
@ -3467,6 +3492,25 @@ protobufjs@^6.10.1:
|
|||||||
"@types/node" "^13.7.0"
|
"@types/node" "^13.7.0"
|
||||||
long "^4.0.0"
|
long "^4.0.0"
|
||||||
|
|
||||||
|
protobufjs@^6.8.8:
|
||||||
|
version "6.11.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b"
|
||||||
|
integrity sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==
|
||||||
|
dependencies:
|
||||||
|
"@protobufjs/aspromise" "^1.1.2"
|
||||||
|
"@protobufjs/base64" "^1.1.2"
|
||||||
|
"@protobufjs/codegen" "^2.0.4"
|
||||||
|
"@protobufjs/eventemitter" "^1.1.0"
|
||||||
|
"@protobufjs/fetch" "^1.1.0"
|
||||||
|
"@protobufjs/float" "^1.0.2"
|
||||||
|
"@protobufjs/inquire" "^1.1.0"
|
||||||
|
"@protobufjs/path" "^1.1.2"
|
||||||
|
"@protobufjs/pool" "^1.1.0"
|
||||||
|
"@protobufjs/utf8" "^1.1.0"
|
||||||
|
"@types/long" "^4.0.1"
|
||||||
|
"@types/node" ">=13.7.0"
|
||||||
|
long "^4.0.0"
|
||||||
|
|
||||||
psl@^1.1.28:
|
psl@^1.1.28:
|
||||||
version "1.8.0"
|
version "1.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
|
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
|
||||||
@ -4245,6 +4289,35 @@ tough-cookie@~2.5.0:
|
|||||||
psl "^1.1.28"
|
psl "^1.1.28"
|
||||||
punycode "^2.1.1"
|
punycode "^2.1.1"
|
||||||
|
|
||||||
|
ts-poet@^4.5.0:
|
||||||
|
version "4.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-poet/-/ts-poet-4.6.1.tgz#015dc823d726655af9f095c900f84ed7c60e2dd3"
|
||||||
|
integrity sha512-DXJ+mBJIDp+jiaUgB4N5I/sczHHDU2FWacdbDNVAVS4Mh4hb7ckpvUWVW7m7/nAOcjR0r4Wt+7AoO7FeJKExfA==
|
||||||
|
dependencies:
|
||||||
|
"@types/prettier" "^1.19.0"
|
||||||
|
lodash "^4.17.15"
|
||||||
|
prettier "^2.0.2"
|
||||||
|
|
||||||
|
ts-proto-descriptors@^1.2.1:
|
||||||
|
version "1.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-proto-descriptors/-/ts-proto-descriptors-1.3.1.tgz#760ebaaa19475b03662f7b358ffea45b9c5348f5"
|
||||||
|
integrity sha512-Cybb3fqceMwA6JzHdC32dIo8eVGVmXrM6TWhdk1XQVVHT/6OQqk0ioyX1dIdu3rCIBhRmWUhUE4HsyK+olmgMw==
|
||||||
|
dependencies:
|
||||||
|
long "^4.0.0"
|
||||||
|
protobufjs "^6.8.8"
|
||||||
|
|
||||||
|
ts-proto@^1.96.0:
|
||||||
|
version "1.96.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-proto/-/ts-proto-1.96.0.tgz#63768d7da533b337aee84db065dd66773bd4cac9"
|
||||||
|
integrity sha512-fKwaGzi8EOCU9xwmcXK917jj1WhFdLbFkPRawQ+5CAZM9eSXr/mpkz/yEctXCiuei364z6jAB2Odb64KCDFTPQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/object-hash" "^1.3.0"
|
||||||
|
dataloader "^1.4.0"
|
||||||
|
object-hash "^1.3.1"
|
||||||
|
protobufjs "^6.8.8"
|
||||||
|
ts-poet "^4.5.0"
|
||||||
|
ts-proto-descriptors "^1.2.1"
|
||||||
|
|
||||||
tsconfig-paths@^3.9.0:
|
tsconfig-paths@^3.9.0:
|
||||||
version "3.9.0"
|
version "3.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b"
|
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b"
|
||||||
|
Loading…
Reference in New Issue
Block a user