Merge branch 'develop' of github.com:thecodingmachine/workadventure into develop
@ -144,9 +144,8 @@ export class GameRoom {
|
|||||||
joinRoomMessage.getUseruuid(),
|
joinRoomMessage.getUseruuid(),
|
||||||
joinRoomMessage.getIpaddress(),
|
joinRoomMessage.getIpaddress(),
|
||||||
position,
|
position,
|
||||||
false,
|
|
||||||
this.positionNotifier,
|
this.positionNotifier,
|
||||||
joinRoomMessage.getAway(),
|
joinRoomMessage.getStatus(),
|
||||||
socket,
|
socket,
|
||||||
joinRoomMessage.getTagList(),
|
joinRoomMessage.getTagList(),
|
||||||
joinRoomMessage.getVisitcardurl(),
|
joinRoomMessage.getVisitcardurl(),
|
||||||
@ -208,6 +207,9 @@ export class GameRoom {
|
|||||||
|
|
||||||
updatePlayerDetails(user: User, playerDetailsMessage: SetPlayerDetailsMessage) {
|
updatePlayerDetails(user: User, playerDetailsMessage: SetPlayerDetailsMessage) {
|
||||||
user.updateDetails(playerDetailsMessage);
|
user.updateDetails(playerDetailsMessage);
|
||||||
|
if (user.group !== undefined && user.silent) {
|
||||||
|
this.leaveGroup(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateUserGroup(user: User): void {
|
private updateUserGroup(user: User): void {
|
||||||
@ -345,21 +347,6 @@ export class GameRoom {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setSilent(user: User, silent: boolean) {
|
|
||||||
if (user.silent === silent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
user.silent = silent;
|
|
||||||
if (silent && user.group !== undefined) {
|
|
||||||
this.leaveGroup(user);
|
|
||||||
}
|
|
||||||
if (!silent) {
|
|
||||||
// If we are back to life, let's trigger a position update to see if we can join some group.
|
|
||||||
this.updatePosition(user, user.getPosition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a user leave a group and closes and destroy the group if the group contains only one remaining person.
|
* Makes a user leave a group and closes and destroy the group if the group contains only one remaining person.
|
||||||
*
|
*
|
||||||
|
@ -5,6 +5,7 @@ import { Movable } from "../Model/Movable";
|
|||||||
import { PositionNotifier } from "../Model/PositionNotifier";
|
import { PositionNotifier } from "../Model/PositionNotifier";
|
||||||
import { ServerDuplexStream } from "grpc";
|
import { ServerDuplexStream } from "grpc";
|
||||||
import {
|
import {
|
||||||
|
AvailabilityStatus,
|
||||||
BatchMessage,
|
BatchMessage,
|
||||||
CompanionMessage,
|
CompanionMessage,
|
||||||
FollowAbortMessage,
|
FollowAbortMessage,
|
||||||
@ -30,9 +31,8 @@ export class User implements Movable {
|
|||||||
public readonly uuid: string,
|
public readonly uuid: string,
|
||||||
public readonly IPAddress: string,
|
public readonly IPAddress: string,
|
||||||
private position: PointInterface,
|
private position: PointInterface,
|
||||||
public silent: boolean,
|
|
||||||
private positionNotifier: PositionNotifier,
|
private positionNotifier: PositionNotifier,
|
||||||
private away: boolean,
|
private status: AvailabilityStatus,
|
||||||
public readonly socket: UserSocket,
|
public readonly socket: UserSocket,
|
||||||
public readonly tags: string[],
|
public readonly tags: string[],
|
||||||
public readonly visitCardUrl: string | null,
|
public readonly visitCardUrl: string | null,
|
||||||
@ -90,8 +90,12 @@ export class User implements Movable {
|
|||||||
return this.outlineColor;
|
return this.outlineColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public isAway(): boolean {
|
public getStatus(): AvailabilityStatus {
|
||||||
return this.away;
|
return this.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get silent(): boolean {
|
||||||
|
return this.status === AvailabilityStatus.SILENT || this.status === AvailabilityStatus.JITSI;
|
||||||
}
|
}
|
||||||
|
|
||||||
get following(): User | undefined {
|
get following(): User | undefined {
|
||||||
@ -134,9 +138,11 @@ export class User implements Movable {
|
|||||||
}
|
}
|
||||||
this.voiceIndicatorShown = details.getShowvoiceindicator()?.getValue();
|
this.voiceIndicatorShown = details.getShowvoiceindicator()?.getValue();
|
||||||
|
|
||||||
const away = details.getAway();
|
const status = details.getStatus();
|
||||||
if (away) {
|
let sendStatusUpdate = false;
|
||||||
this.away = away.getValue();
|
if (status && status !== this.status) {
|
||||||
|
this.status = status;
|
||||||
|
sendStatusUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const playerDetails = new SetPlayerDetailsMessage();
|
const playerDetails = new SetPlayerDetailsMessage();
|
||||||
@ -147,8 +153,8 @@ export class User implements Movable {
|
|||||||
if (this.voiceIndicatorShown !== undefined) {
|
if (this.voiceIndicatorShown !== undefined) {
|
||||||
playerDetails.setShowvoiceindicator(new BoolValue().setValue(this.voiceIndicatorShown));
|
playerDetails.setShowvoiceindicator(new BoolValue().setValue(this.voiceIndicatorShown));
|
||||||
}
|
}
|
||||||
if (details.getAway() !== undefined) {
|
if (sendStatusUpdate) {
|
||||||
playerDetails.setAway(new BoolValue().setValue(this.away));
|
playerDetails.setStatus(details.getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.positionNotifier.updatePlayerDetails(this, playerDetails);
|
this.positionNotifier.updatePlayerDetails(this, playerDetails);
|
||||||
|
@ -22,7 +22,6 @@ import {
|
|||||||
SendUserMessage,
|
SendUserMessage,
|
||||||
ServerToAdminClientMessage,
|
ServerToAdminClientMessage,
|
||||||
SetPlayerDetailsMessage,
|
SetPlayerDetailsMessage,
|
||||||
SilentMessage,
|
|
||||||
UserMovesMessage,
|
UserMovesMessage,
|
||||||
VariableMessage,
|
VariableMessage,
|
||||||
WebRtcSignalToServerMessage,
|
WebRtcSignalToServerMessage,
|
||||||
@ -80,8 +79,6 @@ const roomManager: IRoomManagerServer = {
|
|||||||
user,
|
user,
|
||||||
message.getUsermovesmessage() as UserMovesMessage
|
message.getUsermovesmessage() as UserMovesMessage
|
||||||
);
|
);
|
||||||
} else if (message.hasSilentmessage()) {
|
|
||||||
socketManager.handleSilentMessage(room, user, message.getSilentmessage() as SilentMessage);
|
|
||||||
} else if (message.hasItemeventmessage()) {
|
} else if (message.hasItemeventmessage()) {
|
||||||
socketManager.handleItemEvent(
|
socketManager.handleItemEvent(
|
||||||
room,
|
room,
|
||||||
|
@ -5,7 +5,6 @@ import {
|
|||||||
PointMessage,
|
PointMessage,
|
||||||
RoomJoinedMessage,
|
RoomJoinedMessage,
|
||||||
ServerToClientMessage,
|
ServerToClientMessage,
|
||||||
SilentMessage,
|
|
||||||
SubMessage,
|
SubMessage,
|
||||||
UserMovedMessage,
|
UserMovedMessage,
|
||||||
UserMovesMessage,
|
UserMovesMessage,
|
||||||
@ -160,10 +159,6 @@ export class SocketManager {
|
|||||||
room.updatePlayerDetails(user, playerDetailsMessage);
|
room.updatePlayerDetails(user, playerDetailsMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSilentMessage(room: GameRoom, user: User, silentMessage: SilentMessage) {
|
|
||||||
room.setSilent(user, silentMessage.getSilent());
|
|
||||||
}
|
|
||||||
|
|
||||||
handleItemEvent(room: GameRoom, user: User, itemEventMessage: ItemEventMessage) {
|
handleItemEvent(room: GameRoom, user: User, itemEventMessage: ItemEventMessage) {
|
||||||
const itemEvent = ProtobufUtils.toItemEvent(itemEventMessage);
|
const itemEvent = ProtobufUtils.toItemEvent(itemEventMessage);
|
||||||
|
|
||||||
@ -328,7 +323,7 @@ export class SocketManager {
|
|||||||
userJoinedZoneMessage.setUserid(thing.id);
|
userJoinedZoneMessage.setUserid(thing.id);
|
||||||
userJoinedZoneMessage.setUseruuid(thing.uuid);
|
userJoinedZoneMessage.setUseruuid(thing.uuid);
|
||||||
userJoinedZoneMessage.setName(thing.name);
|
userJoinedZoneMessage.setName(thing.name);
|
||||||
userJoinedZoneMessage.setAway(thing.isAway());
|
userJoinedZoneMessage.setStatus(thing.getStatus());
|
||||||
userJoinedZoneMessage.setCharacterlayersList(ProtobufUtils.toCharacterLayerMessages(thing.characterLayers));
|
userJoinedZoneMessage.setCharacterlayersList(ProtobufUtils.toCharacterLayerMessages(thing.characterLayers));
|
||||||
userJoinedZoneMessage.setPosition(ProtobufUtils.toPositionMessage(thing.getPosition()));
|
userJoinedZoneMessage.setPosition(ProtobufUtils.toPositionMessage(thing.getPosition()));
|
||||||
userJoinedZoneMessage.setFromzone(this.toProtoZone(fromZone));
|
userJoinedZoneMessage.setFromzone(this.toProtoZone(fromZone));
|
||||||
@ -656,7 +651,7 @@ export class SocketManager {
|
|||||||
userJoinedMessage.setUserid(thing.id);
|
userJoinedMessage.setUserid(thing.id);
|
||||||
userJoinedMessage.setUseruuid(thing.uuid);
|
userJoinedMessage.setUseruuid(thing.uuid);
|
||||||
userJoinedMessage.setName(thing.name);
|
userJoinedMessage.setName(thing.name);
|
||||||
userJoinedMessage.setAway(thing.isAway());
|
userJoinedMessage.setStatus(thing.getStatus());
|
||||||
userJoinedMessage.setCharacterlayersList(ProtobufUtils.toCharacterLayerMessages(thing.characterLayers));
|
userJoinedMessage.setCharacterlayersList(ProtobufUtils.toCharacterLayerMessages(thing.characterLayers));
|
||||||
userJoinedMessage.setPosition(ProtobufUtils.toPositionMessage(thing.getPosition()));
|
userJoinedMessage.setPosition(ProtobufUtils.toPositionMessage(thing.getPosition()));
|
||||||
if (thing.visitCardUrl) {
|
if (thing.visitCardUrl) {
|
||||||
|
@ -6,6 +6,7 @@ import { Zone } from "../src/Model/Zone";
|
|||||||
import { Movable } from "../src/Model/Movable";
|
import { Movable } from "../src/Model/Movable";
|
||||||
import { PositionInterface } from "../src/Model/PositionInterface";
|
import { PositionInterface } from "../src/Model/PositionInterface";
|
||||||
import { ZoneSocket } from "../src/RoomManager";
|
import { ZoneSocket } from "../src/RoomManager";
|
||||||
|
import { AvailabilityStatus } from "../src/Messages/generated/messages_pb";
|
||||||
|
|
||||||
describe("PositionNotifier", () => {
|
describe("PositionNotifier", () => {
|
||||||
it("should receive notifications when player moves", () => {
|
it("should receive notifications when player moves", () => {
|
||||||
@ -40,9 +41,8 @@ describe("PositionNotifier", () => {
|
|||||||
moving: false,
|
moving: false,
|
||||||
direction: "down",
|
direction: "down",
|
||||||
},
|
},
|
||||||
false,
|
|
||||||
positionNotifier,
|
positionNotifier,
|
||||||
false,
|
AvailabilityStatus.ONLINE,
|
||||||
{} as UserSocket,
|
{} as UserSocket,
|
||||||
[],
|
[],
|
||||||
null,
|
null,
|
||||||
@ -60,9 +60,8 @@ describe("PositionNotifier", () => {
|
|||||||
moving: false,
|
moving: false,
|
||||||
direction: "down",
|
direction: "down",
|
||||||
},
|
},
|
||||||
false,
|
|
||||||
positionNotifier,
|
positionNotifier,
|
||||||
false,
|
AvailabilityStatus.ONLINE,
|
||||||
{} as UserSocket,
|
{} as UserSocket,
|
||||||
[],
|
[],
|
||||||
null,
|
null,
|
||||||
@ -150,9 +149,8 @@ describe("PositionNotifier", () => {
|
|||||||
moving: false,
|
moving: false,
|
||||||
direction: "down",
|
direction: "down",
|
||||||
},
|
},
|
||||||
false,
|
|
||||||
positionNotifier,
|
positionNotifier,
|
||||||
false,
|
AvailabilityStatus.ONLINE,
|
||||||
{} as UserSocket,
|
{} as UserSocket,
|
||||||
[],
|
[],
|
||||||
null,
|
null,
|
||||||
@ -170,9 +168,8 @@ describe("PositionNotifier", () => {
|
|||||||
moving: false,
|
moving: false,
|
||||||
direction: "down",
|
direction: "down",
|
||||||
},
|
},
|
||||||
false,
|
|
||||||
positionNotifier,
|
positionNotifier,
|
||||||
false,
|
AvailabilityStatus.ONLINE,
|
||||||
{} as UserSocket,
|
{} as UserSocket,
|
||||||
[],
|
[],
|
||||||
null,
|
null,
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
{.section-title.accent.text-primary}
|
{.section-title.accent.text-primary}
|
||||||
# Working with camera
|
# Working with camera
|
||||||
|
|
||||||
## Focusable Zones
|
## Focusable Area
|
||||||
|
|
||||||
It is possible to define special regions on the map that can make the camera zoom and center on themselves. We call them "Focusable Zones". When player gets inside, his camera view will be altered - focused, zoomed and locked on defined zone, like this:
|
It is possible to define special regions on the map that can make the camera zoom and center on themselves. We call them "Focusable Area". When player gets inside, his camera view will be altered - focused, zoomed and locked on defined area, like this:
|
||||||
|
|
||||||
<div class="px-5 card rounded d-inline-block">
|
<div class="px-5 card rounded d-inline-block">
|
||||||
<img class="document-img" src="images/camera/0_focusable_zone.png" alt="" />
|
<img class="document-img" src="images/camera/0_focusable_zone.png" alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
### Adding new **Focusable Zone**:
|
### Adding new **Focusable Area**:
|
||||||
|
|
||||||
1. Make sure you are editing an **Object Layer**
|
1. Make sure you are editing an **Object Layer**
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ It is possible to define special regions on the map that can make the camera zoo
|
|||||||
<img class="document-img" src="images/camera/3_define_new_zone.png" alt="" />
|
<img class="document-img" src="images/camera/3_define_new_zone.png" alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
4. Make sure your object is of type "zone"!
|
4. Make sure your object is of type "area"!
|
||||||
|
|
||||||
<div class="px-5 card rounded d-inline-block">
|
<div class="px-5 card rounded d-inline-block">
|
||||||
<img class="document-img" src="images/camera/4_add_zone_type.png" alt="" />
|
<img class="document-img" src="images/camera/4_add_zone_type.png" alt="" />
|
||||||
@ -53,11 +53,11 @@ It is possible to define special regions on the map that can make the camera zoo
|
|||||||
<img class="document-img" src="images/camera/7_make_sure_checked.png" alt="" />
|
<img class="document-img" src="images/camera/7_make_sure_checked.png" alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
All should be set up now and your new **Focusable Zone** should be working fine!
|
All should be set up now and your new **Focusable Area** should be working fine!
|
||||||
|
|
||||||
### Defining custom zoom margin:
|
### Defining custom zoom margin:
|
||||||
|
|
||||||
If you want, you can add an additional property to control how much should the camera zoom onto focusable zone.
|
If you want, you can add an additional property to control how much should the camera zoom onto focusable area.
|
||||||
|
|
||||||
1. Like before, click on **Add Property**
|
1. Like before, click on **Add Property**
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ If you want, you can add an additional property to control how much should the c
|
|||||||
<img class="document-img" src="images/camera/9_optional_zoom_margin_defined.png" alt="" />
|
<img class="document-img" src="images/camera/9_optional_zoom_margin_defined.png" alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
For example, if you define your zone as a 300x200 rectangle, setting this property to 0.5 *(50%)* means the camera will try to fit within the viewport the entire zone + margin of 50% of its dimensions, so 450x300.
|
For example, if you define your area as a 300x200 rectangle, setting this property to 0.5 *(50%)* means the camera will try to fit within the viewport the entire area + margin of 50% of its dimensions, so 450x300.
|
||||||
|
|
||||||
- No margin defined
|
- No margin defined
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 11 KiB |
@ -9,19 +9,24 @@ On your map, you can define special zones (meeting rooms) that will trigger the
|
|||||||
|
|
||||||
In order to create Jitsi meet zones:
|
In order to create Jitsi meet zones:
|
||||||
|
|
||||||
* You must create a specific layer.
|
* You must create a specific object.
|
||||||
* In layer properties, you MUST add a "`jitsiRoom`" property (of type "`string`"). The value of the property is the name of the room in Jitsi. Note: the name of the room will be "slugified" and prepended with the name of the instance of the map (so that different instances of the map have different rooms)
|
* Object must be of type "`area`"
|
||||||
|
* In object properties, you MUST add a "`jitsiRoom`" property (of type "`string`"). The value of the property is the name of the room in Jitsi. Note: the name of the room will be "slugified" and prepended with a hash of the room URL
|
||||||
* You may also use "jitsiWidth" property (of type "number" between 0 and 100) to control the width of the iframe containing the meeting room.
|
* You may also use "jitsiWidth" property (of type "number" between 0 and 100) to control the width of the iframe containing the meeting room.
|
||||||
|
|
||||||
You can have this layer (i.e. your meeting area) to be selectable as the precise location for your meeting using the [Google Calendar integration for Work Adventure](/integrations/google-calendar). To do so, you must set the `meetingRoomLabel` property. You can provide any name that you would like your meeting room to have (as a string).
|
You can have this object (i.e. your meeting area) to be selectable as the precise location for your meeting using the [Google Calendar integration for Work Adventure](/integrations/google-calendar). To do so, you must set the `meetingRoomLabel` property. You can provide any name that you would like your meeting room to have (as a string).
|
||||||
|
|
||||||
|
{.alert.alert-info}
|
||||||
|
As an alternative, you may also put the `jitsiRoom` properties on a layer (rather than putting them on an "area" object)
|
||||||
|
but we advise to stick with "area" objects for better performance!
|
||||||
|
|
||||||
## Triggering of the "Jitsi meet" action
|
## Triggering of the "Jitsi meet" action
|
||||||
|
|
||||||
By default, Jitsi meet will open when a user enters the zone defined on the map.
|
By default, Jitsi meet will open when a user enters the area defined on the map.
|
||||||
|
|
||||||
It is however possible to trigger Jitsi only on user action. You can do this with the `jitsiTrigger` property.
|
It is however possible to trigger Jitsi only on user action. You can do this with the `jitsiTrigger` property.
|
||||||
|
|
||||||
If you set `jitsiTrigger: onaction`, when the user walks on the layer, an alert message will be displayed at the bottom of the screen:
|
If you set `jitsiTrigger: onaction`, when the user walks on the area, an alert message will be displayed at the bottom of the screen:
|
||||||
|
|
||||||
<figure class="figure">
|
<figure class="figure">
|
||||||
<img src="images/click_space_jitsi.png" class="figure-img img-fluid rounded" alt="" />
|
<img src="images/click_space_jitsi.png" class="figure-img img-fluid rounded" alt="" />
|
||||||
@ -32,7 +37,7 @@ If you set `jitsiTriggerMessage: your message action` you can edit alert message
|
|||||||
|
|
||||||
## Customizing your "Jitsi meet"
|
## Customizing your "Jitsi meet"
|
||||||
|
|
||||||
Your Jitsi meet experience can be customized using Jitsi specific config options. The `jitsiConfig` and `jitsiInterfaceConfig` properties can be used on the Jitsi layer to change the way Jitsi looks and behaves. Those 2 properties are accepting a JSON string.
|
Your Jitsi meet experience can be customized using Jitsi specific config options. The `jitsiConfig` and `jitsiInterfaceConfig` properties can be used on the Jitsi object to change the way Jitsi looks and behaves. Those 2 properties are accepting a JSON string.
|
||||||
|
|
||||||
For instance, use `jitsiConfig: { "startWithAudioMuted": true }` to automatically mute the microphone when someone enters a room. Or use `jitsiInterfaceConfig: { "DEFAULT_BACKGROUND": "#77ee77" }` to change the background color of Jitsi.
|
For instance, use `jitsiConfig: { "startWithAudioMuted": true }` to automatically mute the microphone when someone enters a room. Or use `jitsiInterfaceConfig: { "DEFAULT_BACKGROUND": "#77ee77" }` to change the background color of Jitsi.
|
||||||
|
|
||||||
@ -60,7 +65,7 @@ You can grant moderator rights to some of your members. Jitsi moderators can:
|
|||||||
* Mute everybody expect one speaker
|
* Mute everybody expect one speaker
|
||||||
* Kick users out of the meeting
|
* Kick users out of the meeting
|
||||||
|
|
||||||
In order to grant moderator rights to a given user, you can add a `jitsiRoomAdminTag` property to your Jitsi layer. For instance, if you write a property:
|
In order to grant moderator rights to a given user, you can add a `jitsiRoomAdminTag` property to your Jitsi object. For instance, if you write a property:
|
||||||
|
|
||||||
jitsiRoomAdminTag: speaker
|
jitsiRoomAdminTag: speaker
|
||||||
|
|
||||||
@ -74,7 +79,7 @@ WorkAdventure usually comes with a default Jitsi meet installation. If you are u
|
|||||||
|
|
||||||
You have the possibility, in your map, to override the Jitsi meet instance that will be used by default. This can be useful for regulatory reasons. Maybe your company wants to keep control on the video streams and therefore, wants to self-host a Jitsi instance? Or maybe you want to use a very special configuration or very special version of Jitsi?
|
You have the possibility, in your map, to override the Jitsi meet instance that will be used by default. This can be useful for regulatory reasons. Maybe your company wants to keep control on the video streams and therefore, wants to self-host a Jitsi instance? Or maybe you want to use a very special configuration or very special version of Jitsi?
|
||||||
|
|
||||||
Use the `jitsiUrl` property to in the Jitsi layer to specify the Jitsi instance that should be used. Beware, `jitsiUrl` takes in parameter a **domain name**, without the protocol. So you should use:
|
Use the `jitsiUrl` property to in the Jitsi object to specify the Jitsi instance that should be used. Beware, `jitsiUrl` takes in parameter a **domain name**, without the protocol. So you should use:
|
||||||
`jitsiUrl: meet.jit.si`
|
`jitsiUrl: meet.jit.si`
|
||||||
and not
|
and not
|
||||||
`jitsiUrl: https://meet.jit.si`
|
`jitsiUrl: https://meet.jit.si`
|
||||||
@ -82,3 +87,15 @@ and not
|
|||||||
{.alert.alert-info}
|
{.alert.alert-info}
|
||||||
When you use `jitsiUrl`, the targeted Jitsi instance must be public. You cannot use moderation features or the JWT
|
When you use `jitsiUrl`, the targeted Jitsi instance must be public. You cannot use moderation features or the JWT
|
||||||
tokens authentication with maps configured using the `jitsiUrl` property.
|
tokens authentication with maps configured using the `jitsiUrl` property.
|
||||||
|
|
||||||
|
## Full control over the Jitsi room name
|
||||||
|
|
||||||
|
By default, the name of the room will be "slugified" and prepended with a hash of the room URL.
|
||||||
|
This is what you want most of the time. Indeed, different maps with the same Jitsi room name (the same `jitsiRoom` property) will not share the same Jitsi room instance.
|
||||||
|
|
||||||
|
However, sometimes, you may actually want to have different WorkAdventure meeting rooms that are actually sharing
|
||||||
|
the same Jitsi meet meeting room. Or if you are pointing to a custom Jitsi server (using the `jitsiUrl` property),
|
||||||
|
you may want to point to a specific existing room.
|
||||||
|
|
||||||
|
For all those use cases, you can use `jitsiNoPrefix: true`. This will remove the automatic prefixing
|
||||||
|
of the hash and will give you full control on the Jitsi room name.
|
||||||
|
@ -10,8 +10,9 @@ on the right side of the screen)
|
|||||||
|
|
||||||
In order to create a zone that opens websites:
|
In order to create a zone that opens websites:
|
||||||
|
|
||||||
* You must create a specific layer.
|
* You must create a specific object.
|
||||||
* In layer properties, you MUST add a "`openWebsite`" property (of type "`string`"). The value of the property is the URL of the website to open (the URL must start with "https://")
|
* Object must be of type "`area`"
|
||||||
|
* In object properties, you MUST add a "`openWebsite`" property (of type "`string`"). The value of the property is the URL of the website to open (the URL must start with "https://")
|
||||||
* You may also use "`openWebsiteWidth`" property (of type "`int`" or "`float`" between 0 and 100) to control the width of the iframe.
|
* You may also use "`openWebsiteWidth`" property (of type "`int`" or "`float`" between 0 and 100) to control the width of the iframe.
|
||||||
* You may also use "`openTab`" property (of type "`string`") to open in a new tab instead.
|
* You may also use "`openTab`" property (of type "`string`") to open in a new tab instead.
|
||||||
|
|
||||||
@ -19,6 +20,10 @@ In order to create a zone that opens websites:
|
|||||||
A website can explicitly forbid another website from loading it in an iFrame using
|
A website can explicitly forbid another website from loading it in an iFrame using
|
||||||
the [X-Frame-Options HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options).
|
the [X-Frame-Options HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options).
|
||||||
|
|
||||||
|
{.alert.alert-info}
|
||||||
|
As an alternative, you may also put the `openWebsite` properties on a layer (rather than putting them on an "area" object)
|
||||||
|
but we advise to stick with "area" objects for better performance!
|
||||||
|
|
||||||
## Integrating a Youtube video
|
## Integrating a Youtube video
|
||||||
|
|
||||||
A common use case is to use `openWebsite` to open a Youtube video.
|
A common use case is to use `openWebsite` to open a Youtube video.
|
||||||
@ -43,7 +48,7 @@ By default, the iFrame will open when a user enters the zone defined on the map.
|
|||||||
|
|
||||||
It is however possible to trigger the iFrame only on user action. You can do this with the `openWebsiteTrigger` property.
|
It is however possible to trigger the iFrame only on user action. You can do this with the `openWebsiteTrigger` property.
|
||||||
|
|
||||||
If you set `openWebsiteTrigger: onaction`, when the user walks on the layer, an alert message will be displayed at the bottom of the screen:
|
If you set `openWebsiteTrigger: onaction`, when the user walks on the area, an alert message will be displayed at the bottom of the screen:
|
||||||
|
|
||||||
<figure class="figure">
|
<figure class="figure">
|
||||||
<img src="images/click_space_open_website.jpg" class="figure-img img-fluid rounded" alt="" />
|
<img src="images/click_space_open_website.jpg" class="figure-img img-fluid rounded" alt="" />
|
||||||
@ -52,7 +57,7 @@ If you set `openWebsiteTrigger: onaction`, when the user walks on the layer, an
|
|||||||
|
|
||||||
If you set `openWebsiteTriggerMessage: your message action` you can edit alert message displayed. If is not defined, the default message displayed is 'Press on SPACE to open the web site'.
|
If you set `openWebsiteTriggerMessage: your message action` you can edit alert message displayed. If is not defined, the default message displayed is 'Press on SPACE to open the web site'.
|
||||||
|
|
||||||
If you set `openWebsiteTrigger: onicon`, when the user walks on the layer, an icon will be displayed at the bottom of the screen:
|
If you set `openWebsiteTrigger: onicon`, when the user walks on the area, an icon will be displayed at the bottom of the screen:
|
||||||
|
|
||||||
<figure class="figure">
|
<figure class="figure">
|
||||||
<img src="images/icon_open_website.png" class="figure-img img-fluid rounded" alt="" />
|
<img src="images/icon_open_website.png" class="figure-img img-fluid rounded" alt="" />
|
||||||
@ -78,6 +83,6 @@ Cowebsites allow you to have several sites open at the same time.
|
|||||||
|
|
||||||
If you want to open a Jitsi and another page it's easy!
|
If you want to open a Jitsi and another page it's easy!
|
||||||
|
|
||||||
You have just to [add a Jitsi to the map](meeting-rooms.md) and [add a co-website](opening-a-website.md#the-openwebsite-property) on the same layer.
|
You have just to [add a Jitsi to the map](meeting-rooms.md) and [add a co-website](opening-a-website.md#the-openwebsite-property) on the same object.
|
||||||
|
|
||||||
It's done!
|
It's done!
|
||||||
|
@ -9,8 +9,13 @@ On your map, you can define special silent zones where nobody is allowed to talk
|
|||||||
|
|
||||||
In order to create a silent zone:
|
In order to create a silent zone:
|
||||||
|
|
||||||
* You must create a specific layer.
|
* You must create a specific object.
|
||||||
* In layer properties, you MUST add a boolean "`silent`" property. If the silent property is checked, the users are entering the silent zone when they walk on any tile of the layer.
|
* Object must be of type "`area`"
|
||||||
|
* In object properties, you MUST add a boolean "`silent`" property. If the silent property is checked, the users are entering the silent zone when they walk on the area.
|
||||||
|
|
||||||
|
{.alert.alert-info}
|
||||||
|
As an alternative, you may also put the `silent` property on a layer (rather than putting them on an "area" object)
|
||||||
|
but we advise to stick with "area" objects for better performance!
|
||||||
|
|
||||||
## Playing sounds or background music
|
## Playing sounds or background music
|
||||||
|
|
||||||
@ -18,10 +23,15 @@ Your map can define special zones where a sound or background music will automat
|
|||||||
|
|
||||||
In order to create a zone that triggers sounds/music:
|
In order to create a zone that triggers sounds/music:
|
||||||
|
|
||||||
* You must create a specific layer.
|
* You must create a specific object.
|
||||||
* In layer properties, you MUST add a "`playAudio`" property. The value of the property is a URL to an MP3 file that will be played. The URL can be relative to the URL of the map.
|
* Object must be of type "`area`"
|
||||||
|
* In object properties, you MUST add a "`playAudio`" property. The value of the property is a URL to an MP3 file that will be played. The URL can be relative to the URL of the map.
|
||||||
* You may use the boolean property "`audioLoop`" to make the sound loop (thanks captain obvious).
|
* You may use the boolean property "`audioLoop`" to make the sound loop (thanks captain obvious).
|
||||||
* If the "`audioVolume`" property is set, the audio player uses either the value of the property or the last volume set by the user - whichever is smaller. This property is a float from 0 to 1.0
|
* If the "`audioVolume`" property is set, the audio player uses either the value of the property or the last volume set by the user - whichever is smaller. This property is a float from 0 to 1.0
|
||||||
|
|
||||||
{.alert.alert-info}
|
{.alert.alert-info}
|
||||||
"`playAudioLoop`" is deprecated and should not be used anymore.
|
"`playAudioLoop`" is deprecated and should not be used anymore.
|
||||||
|
|
||||||
|
{.alert.alert-info}
|
||||||
|
As an alternative, you may also put the `playAudio` properties on a layer (rather than putting them on an "area" object)
|
||||||
|
but we advise to stick with "area" objects for better performance!
|
||||||
|
@ -87,11 +87,11 @@ Repeat for every tile that should be "collidable".
|
|||||||
In the next sections, you will see how you can add behaviour on your map by adding "properties".
|
In the next sections, you will see how you can add behaviour on your map by adding "properties".
|
||||||
You can add properties for a variety of features: putting exits, opening websites, meeting rooms, silent zones, etc...
|
You can add properties for a variety of features: putting exits, opening websites, meeting rooms, silent zones, etc...
|
||||||
|
|
||||||
You can add properties either on individual tiles of a tileset OR on a complete layer.
|
You can add properties either on individual tiles of a tileset, on Tiled object OR on a complete layer.
|
||||||
|
|
||||||
If you put a property on a layer, it will be triggered if your Woka walks on any tile of the layer.
|
If you put a property on a object or layer, it will be triggered if your Woka walks on object area / any tile of the layer.
|
||||||
|
|
||||||
The exception is the "collides" property that can only be set on tiles, but not on a complete layer.
|
The exception is the "collides" property that can only be set on tiles, but not on an object or on complete layer.
|
||||||
|
|
||||||
## Insert helpful information in your map
|
## Insert helpful information in your map
|
||||||
|
|
||||||
|
BIN
front/public/resources/icons/icon_status_indicator_inside.png
Normal file
After Width: | Height: | Size: 123 B |
BIN
front/public/resources/icons/icon_status_indicator_outline.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
@ -9,7 +9,7 @@ class AnalyticsClient {
|
|||||||
constructor() {
|
constructor() {
|
||||||
if (POSTHOG_API_KEY && POSTHOG_URL) {
|
if (POSTHOG_API_KEY && POSTHOG_URL) {
|
||||||
this.posthogPromise = import("posthog-js").then(({ default: posthog }) => {
|
this.posthogPromise = import("posthog-js").then(({ default: posthog }) => {
|
||||||
posthog.init(POSTHOG_API_KEY, { api_host: POSTHOG_URL, disable_cookie: true });
|
posthog.init(POSTHOG_API_KEY, { api_host: POSTHOG_URL });
|
||||||
//the posthog toolbar need a reference in window to be able to work
|
//the posthog toolbar need a reference in window to be able to work
|
||||||
window.posthog = posthog;
|
window.posthog = posthog;
|
||||||
return posthog;
|
return posthog;
|
||||||
|
@ -7,4 +7,4 @@ export const isChangeZoneEvent = z.object({
|
|||||||
/**
|
/**
|
||||||
* A message sent from the game to the iFrame when a user enters or leaves a zone.
|
* A message sent from the game to the iFrame when a user enters or leaves a zone.
|
||||||
*/
|
*/
|
||||||
export type ChangeZoneEvent = z.infer<typeof isChangeZoneEvent>;
|
export type ChangeAreaEvent = z.infer<typeof isChangeZoneEvent>;
|
@ -29,7 +29,7 @@ import { isMenuRegisterEvent, isUnregisterMenuEvent } from "./ui/MenuRegisterEve
|
|||||||
import type { ChangeLayerEvent } from "./ChangeLayerEvent";
|
import type { ChangeLayerEvent } from "./ChangeLayerEvent";
|
||||||
import { isPlayerPosition } from "./PlayerPosition";
|
import { isPlayerPosition } from "./PlayerPosition";
|
||||||
import type { WasCameraUpdatedEvent } from "./WasCameraUpdatedEvent";
|
import type { WasCameraUpdatedEvent } from "./WasCameraUpdatedEvent";
|
||||||
import type { ChangeZoneEvent } from "./ChangeZoneEvent";
|
import type { ChangeAreaEvent } from "./ChangeAreaEvent";
|
||||||
import { isCameraSetEvent } from "./CameraSetEvent";
|
import { isCameraSetEvent } from "./CameraSetEvent";
|
||||||
import { isCameraFollowPlayerEvent } from "./CameraFollowPlayerEvent";
|
import { isCameraFollowPlayerEvent } from "./CameraFollowPlayerEvent";
|
||||||
import { isColorEvent } from "./ColorEvent";
|
import { isColorEvent } from "./ColorEvent";
|
||||||
@ -163,8 +163,8 @@ export interface IframeResponseEventMap {
|
|||||||
leaveEvent: EnterLeaveEvent;
|
leaveEvent: EnterLeaveEvent;
|
||||||
enterLayerEvent: ChangeLayerEvent;
|
enterLayerEvent: ChangeLayerEvent;
|
||||||
leaveLayerEvent: ChangeLayerEvent;
|
leaveLayerEvent: ChangeLayerEvent;
|
||||||
enterZoneEvent: ChangeZoneEvent;
|
enterAreaEvent: ChangeAreaEvent;
|
||||||
leaveZoneEvent: ChangeZoneEvent;
|
leaveAreaEvent: ChangeAreaEvent;
|
||||||
buttonClickedEvent: ButtonClickedEvent;
|
buttonClickedEvent: ButtonClickedEvent;
|
||||||
remotePlayerClickedEvent: RemotePlayerClickedEvent;
|
remotePlayerClickedEvent: RemotePlayerClickedEvent;
|
||||||
actionsMenuActionClickedEvent: ActionsMenuActionClickedEvent;
|
actionsMenuActionClickedEvent: ActionsMenuActionClickedEvent;
|
||||||
|
@ -28,7 +28,7 @@ import { ModifyEmbeddedWebsiteEvent } 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 { WasCameraUpdatedEvent } from "./Events/WasCameraUpdatedEvent";
|
||||||
import type { ChangeZoneEvent } from "./Events/ChangeZoneEvent";
|
import type { ChangeAreaEvent } from "./Events/ChangeAreaEvent";
|
||||||
import { CameraSetEvent } from "./Events/CameraSetEvent";
|
import { CameraSetEvent } from "./Events/CameraSetEvent";
|
||||||
import { CameraFollowPlayerEvent } from "./Events/CameraFollowPlayerEvent";
|
import { CameraFollowPlayerEvent } from "./Events/CameraFollowPlayerEvent";
|
||||||
import type { RemotePlayerClickedEvent } from "./Events/RemotePlayerClickedEvent";
|
import type { RemotePlayerClickedEvent } from "./Events/RemotePlayerClickedEvent";
|
||||||
@ -450,21 +450,21 @@ class IframeListener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sendEnterZoneEvent(zoneName: string) {
|
sendEnterAreaEvent(areaName: string) {
|
||||||
this.postMessage({
|
this.postMessage({
|
||||||
type: "enterZoneEvent",
|
type: "enterAreaEvent",
|
||||||
data: {
|
data: {
|
||||||
name: zoneName,
|
name: areaName,
|
||||||
} as ChangeZoneEvent,
|
} as ChangeAreaEvent,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sendLeaveZoneEvent(zoneName: string) {
|
sendLeaveAreaEvent(areaName: string) {
|
||||||
this.postMessage({
|
this.postMessage({
|
||||||
type: "leaveZoneEvent",
|
type: "leaveAreaEvent",
|
||||||
data: {
|
data: {
|
||||||
name: zoneName,
|
name: areaName,
|
||||||
} as ChangeZoneEvent,
|
} as ChangeAreaEvent,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { isSilentStore, requestedCameraState, requestedMicrophoneState } from "../../Stores/MediaStore";
|
import { requestedCameraState, requestedMicrophoneState, silentStore } from "../../Stores/MediaStore";
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
import { WorkAdventureDesktopApi } from "@wa-preload-app";
|
import { WorkAdventureDesktopApi } from "@wa-preload-app";
|
||||||
|
|
||||||
@ -36,8 +36,8 @@ class DesktopApi {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
isSilentStore.subscribe((value) => {
|
silentStore.subscribe((silent) => {
|
||||||
this.isSilent = value;
|
this.isSilent = silent;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { requestedScreenSharingState, screenSharingAvailableStore } from "../Stores/ScreenSharingStore";
|
import { requestedScreenSharingState, screenSharingAvailableStore } from "../Stores/ScreenSharingStore";
|
||||||
import { isSilentStore, requestedCameraState, requestedMicrophoneState } from "../Stores/MediaStore";
|
import { requestedCameraState, requestedMicrophoneState, silentStore } from "../Stores/MediaStore";
|
||||||
import monitorImg from "./images/monitor.svg";
|
import monitorImg from "./images/monitor.svg";
|
||||||
import monitorCloseImg from "./images/monitor-close.svg";
|
import monitorCloseImg from "./images/monitor-close.svg";
|
||||||
import cinemaImg from "./images/cinema.svg";
|
import cinemaImg from "./images/cinema.svg";
|
||||||
@ -13,7 +13,6 @@
|
|||||||
import lockImg from "./images/lock.svg";
|
import lockImg from "./images/lock.svg";
|
||||||
import { LayoutMode } from "../WebRtc/LayoutManager";
|
import { LayoutMode } from "../WebRtc/LayoutManager";
|
||||||
import { peerStore } from "../Stores/PeerStore";
|
import { peerStore } from "../Stores/PeerStore";
|
||||||
import { onDestroy } from "svelte";
|
|
||||||
import { embedScreenLayout } from "../Stores/EmbedScreensStore";
|
import { embedScreenLayout } from "../Stores/EmbedScreensStore";
|
||||||
import { followRoleStore, followStateStore, followUsersStore } from "../Stores/FollowStore";
|
import { followRoleStore, followStateStore, followUsersStore } from "../Stores/FollowStore";
|
||||||
import { gameManager } from "../Phaser/Game/GameManager";
|
import { gameManager } from "../Phaser/Game/GameManager";
|
||||||
@ -22,7 +21,7 @@
|
|||||||
const gameScene = gameManager.getCurrentGameScene();
|
const gameScene = gameManager.getCurrentGameScene();
|
||||||
|
|
||||||
function screenSharingClick(): void {
|
function screenSharingClick(): void {
|
||||||
if (isSilent) return;
|
if ($silentStore) return;
|
||||||
if ($requestedScreenSharingState === true) {
|
if ($requestedScreenSharingState === true) {
|
||||||
requestedScreenSharingState.disableScreenSharing();
|
requestedScreenSharingState.disableScreenSharing();
|
||||||
} else {
|
} else {
|
||||||
@ -31,7 +30,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cameraClick(): void {
|
function cameraClick(): void {
|
||||||
if (isSilent) return;
|
if ($silentStore) return;
|
||||||
if ($requestedCameraState === true) {
|
if ($requestedCameraState === true) {
|
||||||
requestedCameraState.disableWebcam();
|
requestedCameraState.disableWebcam();
|
||||||
} else {
|
} else {
|
||||||
@ -40,7 +39,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function microphoneClick(): void {
|
function microphoneClick(): void {
|
||||||
if (isSilent) return;
|
if ($silentStore) return;
|
||||||
if ($requestedMicrophoneState === true) {
|
if ($requestedMicrophoneState === true) {
|
||||||
requestedMicrophoneState.disableMicrophone();
|
requestedMicrophoneState.disableMicrophone();
|
||||||
} else {
|
} else {
|
||||||
@ -75,12 +74,6 @@
|
|||||||
function lockClick() {
|
function lockClick() {
|
||||||
gameScene.connection?.emitLockGroup(!$currentPlayerGroupLockStateStore);
|
gameScene.connection?.emitLockGroup(!$currentPlayerGroupLockStateStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
let isSilent: boolean;
|
|
||||||
const unsubscribeIsSilent = isSilentStore.subscribe((value) => {
|
|
||||||
isSilent = value;
|
|
||||||
});
|
|
||||||
onDestroy(unsubscribeIsSilent);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="btn-cam-action">
|
<div class="btn-cam-action">
|
||||||
@ -94,7 +87,7 @@
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
class="btn-follow nes-btn is-dark"
|
class="btn-follow nes-btn is-dark"
|
||||||
class:hide={($peerStore.size === 0 && $followStateStore === "off") || isSilent}
|
class:hide={($peerStore.size === 0 && $followStateStore === "off") || $silentStore}
|
||||||
class:disabled={$followStateStore !== "off"}
|
class:disabled={$followStateStore !== "off"}
|
||||||
on:click={followClick}
|
on:click={followClick}
|
||||||
>
|
>
|
||||||
@ -103,7 +96,7 @@
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
class="btn-lock nes-btn is-dark"
|
class="btn-lock nes-btn is-dark"
|
||||||
class:hide={$peerStore.size === 0 || isSilent}
|
class:hide={$peerStore.size === 0 || $silentStore}
|
||||||
class:disabled={$currentPlayerGroupLockStateStore}
|
class:disabled={$currentPlayerGroupLockStateStore}
|
||||||
on:click={lockClick}
|
on:click={lockClick}
|
||||||
>
|
>
|
||||||
@ -113,26 +106,26 @@
|
|||||||
<div
|
<div
|
||||||
class="btn-monitor nes-btn is-dark"
|
class="btn-monitor nes-btn is-dark"
|
||||||
on:click={screenSharingClick}
|
on:click={screenSharingClick}
|
||||||
class:hide={!$screenSharingAvailableStore || isSilent}
|
class:hide={!$screenSharingAvailableStore || $silentStore}
|
||||||
class:enabled={$requestedScreenSharingState}
|
class:enabled={$requestedScreenSharingState}
|
||||||
>
|
>
|
||||||
{#if $requestedScreenSharingState && !isSilent}
|
{#if $requestedScreenSharingState && !$silentStore}
|
||||||
<img class="noselect" src={monitorImg} alt="Start screen sharing" />
|
<img class="noselect" src={monitorImg} alt="Start screen sharing" />
|
||||||
{:else}
|
{:else}
|
||||||
<img class="noselect" src={monitorCloseImg} alt="Stop screen sharing" />
|
<img class="noselect" src={monitorCloseImg} alt="Stop screen sharing" />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-video nes-btn is-dark" on:click={cameraClick} class:disabled={!$requestedCameraState || isSilent}>
|
<div class="btn-video nes-btn is-dark" on:click={cameraClick} class:disabled={!$requestedCameraState || $silentStore}>
|
||||||
{#if $requestedCameraState && !isSilent}
|
{#if $requestedCameraState && !$silentStore}
|
||||||
<img class="noselect" src={cinemaImg} alt="Turn on webcam" />
|
<img class="noselect" src={cinemaImg} alt="Turn on webcam" />
|
||||||
{:else}
|
{:else}
|
||||||
<img class="noselect" src={cinemaCloseImg} alt="Turn off webcam" />
|
<img class="noselect" src={cinemaCloseImg} alt="Turn off webcam" />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btn-micro nes-btn is-dark" on:click={microphoneClick} class:disabled={!$requestedMicrophoneState || isSilent}>
|
<div class="btn-micro nes-btn is-dark" on:click={microphoneClick} class:disabled={!$requestedMicrophoneState || $silentStore}>
|
||||||
{#if $requestedMicrophoneState && !isSilent}
|
{#if $requestedMicrophoneState && !$silentStore}
|
||||||
<img class="noselect" src={microphoneImg} alt="Turn on microphone" />
|
<img class="noselect" src={microphoneImg} alt="Turn on microphone" />
|
||||||
{:else}
|
{:else}
|
||||||
<img class="noselect" src={microphoneCloseImg} alt="Turn off microphone" />
|
<img class="noselect" src={microphoneCloseImg} alt="Turn off microphone" />
|
||||||
|
@ -47,7 +47,13 @@
|
|||||||
{#if !canShare}
|
{#if !canShare}
|
||||||
<section class="share-url not-mobile">
|
<section class="share-url not-mobile">
|
||||||
<h3>{$LL.menu.invite.description()}</h3>
|
<h3>{$LL.menu.invite.description()}</h3>
|
||||||
<input type="text" readonly id="input-share-link" class="link-url" value={location.toString()} />
|
<input
|
||||||
|
type="text"
|
||||||
|
readonly
|
||||||
|
id="input-share-link"
|
||||||
|
class="link-url nes-input is-dark"
|
||||||
|
value={location.toString()}
|
||||||
|
/>
|
||||||
<button type="button" class="nes-btn is-primary" on:click={copyLink}>{$LL.menu.invite.copy()}</button>
|
<button type="button" class="nes-btn is-primary" on:click={copyLink}>{$LL.menu.invite.copy()}</button>
|
||||||
</section>
|
</section>
|
||||||
{:else}
|
{:else}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
import ProfileSubMenu from "./ProfileSubMenu.svelte";
|
import ProfileSubMenu from "./ProfileSubMenu.svelte";
|
||||||
import WorldsSubMenu from "./WorldsSubMenu.svelte";
|
import WorldsSubMenu from "./WorldsSubMenu.svelte";
|
||||||
import AboutRoomSubMenu from "./AboutRoomSubMenu.svelte";
|
import AboutRoomSubMenu from "./AboutRoomSubMenu.svelte";
|
||||||
import GlobalMessageSubMenu from "./GlobalMessagesSubMenu.svelte";
|
|
||||||
import ContactSubMenu from "./ContactSubMenu.svelte";
|
import ContactSubMenu from "./ContactSubMenu.svelte";
|
||||||
import CustomSubMenu from "./CustomSubMenu.svelte";
|
import CustomSubMenu from "./CustomSubMenu.svelte";
|
||||||
import GuestSubMenu from "./GuestSubMenu.svelte";
|
import GuestSubMenu from "./GuestSubMenu.svelte";
|
||||||
@ -26,16 +25,16 @@
|
|||||||
let props: { url: string; allowApi: boolean };
|
let props: { url: string; allowApi: boolean };
|
||||||
let unsubscriberSubMenuStore: Unsubscriber;
|
let unsubscriberSubMenuStore: Unsubscriber;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(async () => {
|
||||||
unsubscriberSubMenuStore = subMenusStore.subscribe(() => {
|
unsubscriberSubMenuStore = subMenusStore.subscribe(() => {
|
||||||
if (!$subMenusStore.includes(activeSubMenu)) {
|
if (!$subMenusStore.includes(activeSubMenu)) {
|
||||||
switchMenu($subMenusStore[0]);
|
void switchMenu($subMenusStore[0]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
checkSubMenuToShow();
|
checkSubMenuToShow();
|
||||||
|
|
||||||
switchMenu($subMenusStore[0]);
|
await switchMenu($subMenusStore[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
@ -44,7 +43,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function switchMenu(menu: MenuItem) {
|
async function switchMenu(menu: MenuItem) {
|
||||||
if (menu.type === "translated") {
|
if (menu.type === "translated") {
|
||||||
activeSubMenu = menu;
|
activeSubMenu = menu;
|
||||||
switch (menu.key) {
|
switch (menu.key) {
|
||||||
@ -64,7 +63,7 @@
|
|||||||
activeComponent = AboutRoomSubMenu;
|
activeComponent = AboutRoomSubMenu;
|
||||||
break;
|
break;
|
||||||
case SubMenusInterface.globalMessages:
|
case SubMenusInterface.globalMessages:
|
||||||
activeComponent = GlobalMessageSubMenu;
|
activeComponent = (await import("./GlobalMessagesSubMenu.svelte")).default;
|
||||||
break;
|
break;
|
||||||
case SubMenusInterface.contact:
|
case SubMenusInterface.contact:
|
||||||
activeComponent = ContactSubMenu;
|
activeComponent = ContactSubMenu;
|
||||||
@ -115,7 +114,7 @@
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="nes-btn {activeSubMenu === submenu ? 'is-disabled' : ''}"
|
class="nes-btn {activeSubMenu === submenu ? 'is-disabled' : ''}"
|
||||||
on:click|preventDefault={() => switchMenu(submenu)}
|
on:click|preventDefault={() => void switchMenu(submenu)}
|
||||||
>
|
>
|
||||||
{translateMenuName(submenu)}
|
{translateMenuName(submenu)}
|
||||||
</button>
|
</button>
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { gameManager } from "../../Phaser/Game/GameManager";
|
import { gameManager } from "../../Phaser/Game/GameManager";
|
||||||
import { SelectCompanionScene, SelectCompanionSceneName } from "../../Phaser/Login/SelectCompanionScene";
|
import { SelectCompanionScene, SelectCompanionSceneName } from "../../Phaser/Login/SelectCompanionScene";
|
||||||
import { menuIconVisiblilityStore, menuVisiblilityStore, userIsConnected } from "../../Stores/MenuStore";
|
import {
|
||||||
|
menuIconVisiblilityStore,
|
||||||
|
menuVisiblilityStore,
|
||||||
|
userIsConnected,
|
||||||
|
profileAvailable,
|
||||||
|
getProfileUrl,
|
||||||
|
} from "../../Stores/MenuStore";
|
||||||
import { selectCompanionSceneVisibleStore } from "../../Stores/SelectCompanionStore";
|
import { selectCompanionSceneVisibleStore } from "../../Stores/SelectCompanionStore";
|
||||||
import { loginSceneVisibleStore } from "../../Stores/LoginSceneStore";
|
import { loginSceneVisibleStore } from "../../Stores/LoginSceneStore";
|
||||||
import { selectCharacterSceneVisibleStore } from "../../Stores/SelectCharacterStore";
|
import { selectCharacterSceneVisibleStore } from "../../Stores/SelectCharacterStore";
|
||||||
import { SelectCharacterScene, SelectCharacterSceneName } from "../../Phaser/Login/SelectCharacterScene";
|
import { SelectCharacterScene, SelectCharacterSceneName } from "../../Phaser/Login/SelectCharacterScene";
|
||||||
import { connectionManager } from "../../Connexion/ConnectionManager";
|
import { connectionManager } from "../../Connexion/ConnectionManager";
|
||||||
import { PROFILE_URL } from "../../Enum/EnvironmentVariable";
|
import { PROFILE_URL } from "../../Enum/EnvironmentVariable";
|
||||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
|
||||||
import { EnableCameraScene, EnableCameraSceneName } from "../../Phaser/Login/EnableCameraScene";
|
import { EnableCameraScene, EnableCameraSceneName } from "../../Phaser/Login/EnableCameraScene";
|
||||||
import { enableCameraSceneVisibilityStore } from "../../Stores/MediaStore";
|
import { enableCameraSceneVisibilityStore } from "../../Stores/MediaStore";
|
||||||
import btnProfileSubMenuCamera from "../images/btn-menu-profile-camera.svg";
|
import btnProfileSubMenuCamera from "../images/btn-menu-profile-camera.svg";
|
||||||
@ -39,10 +44,6 @@
|
|||||||
return connectionManager.logout();
|
return connectionManager.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getProfileUrl() {
|
|
||||||
return PROFILE_URL + `?token=${localUserStore.getAuthToken()}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function openEnableCameraScene() {
|
function openEnableCameraScene() {
|
||||||
disableMenuStores();
|
disableMenuStores();
|
||||||
enableCameraSceneVisibilityStore.showEnableCameraScene();
|
enableCameraSceneVisibilityStore.showEnableCameraScene();
|
||||||
@ -75,7 +76,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
{#if $userIsConnected}
|
{#if $userIsConnected && $profileAvailable}
|
||||||
<section>
|
<section>
|
||||||
{#if PROFILE_URL != undefined}
|
{#if PROFILE_URL != undefined}
|
||||||
<iframe title="profile" src={getProfileUrl()} />
|
<iframe title="profile" src={getProfileUrl()} />
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
|
import { isMediaBreakpointUp } from "../../Utils/BreakpointsUtils";
|
||||||
import { audioManagerVolumeStore } from "../../Stores/AudioManagerStore";
|
import { audioManagerVolumeStore } from "../../Stores/AudioManagerStore";
|
||||||
|
|
||||||
|
import infoImg from "../images/info.svg";
|
||||||
|
|
||||||
let fullscreen: boolean = localUserStore.getFullscreen();
|
let fullscreen: boolean = localUserStore.getFullscreen();
|
||||||
let notification: boolean = localUserStore.getNotification() === "granted";
|
let notification: boolean = localUserStore.getNotification() === "granted";
|
||||||
let forceCowebsiteTrigger: boolean = localUserStore.getForceCowebsiteTrigger();
|
let forceCowebsiteTrigger: boolean = localUserStore.getForceCowebsiteTrigger();
|
||||||
@ -179,8 +181,15 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h3>{$LL.menu.settings.privacySettings.title()}</h3>
|
<div class="tooltip">
|
||||||
<p>{$LL.menu.settings.privacySettings.explanation()}</p>
|
<h3>
|
||||||
|
<span class="dotted-bottom">{$LL.menu.settings.privacySettings.title()}</span>
|
||||||
|
<img src={infoImg} alt="info icon" width="23px" height="23px" />
|
||||||
|
</h3>
|
||||||
|
<div class="nes-balloon away-tooltip-container from-left flex">
|
||||||
|
<p class="away-tooltip-text">{$LL.menu.settings.privacySettings.explanation()}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" class="nes-checkbox is-dark" bind:checked={valueCameraPrivacySettings} />
|
<input type="checkbox" class="nes-checkbox is-dark" bind:checked={valueCameraPrivacySettings} />
|
||||||
<span>{$LL.menu.settings.privacySettings.cameraToggle()}</span>
|
<span>{$LL.menu.settings.privacySettings.cameraToggle()}</span>
|
||||||
@ -286,6 +295,35 @@
|
|||||||
.languages-switcher option {
|
.languages-switcher option {
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Tooltip
|
||||||
|
.tooltip {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.away-tooltip-container {
|
||||||
|
background-color: #fff;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 45%;
|
||||||
|
left: 55%;
|
||||||
|
|
||||||
|
visibility: hidden;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.away-tooltip-text {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dotted-bottom {
|
||||||
|
border-bottom: 1px dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip:hover {
|
||||||
|
.away-tooltip-container {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include media-breakpoint-up(md) {
|
@include media-breakpoint-up(md) {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
import { onDestroy, onMount } from "svelte";
|
import { onDestroy, onMount } from "svelte";
|
||||||
import { gameManager } from "../../Phaser/Game/GameManager";
|
import { gameManager } from "../../Phaser/Game/GameManager";
|
||||||
import { AdminMessageEventTypes } from "../../Connexion/AdminMessagesService";
|
import { AdminMessageEventTypes } from "../../Connexion/AdminMessagesService";
|
||||||
import type { Quill } from "quill";
|
import Quill from "quill";
|
||||||
import type { PlayGlobalMessageInterface } from "../../Connexion/ConnexionModels";
|
import type { PlayGlobalMessageInterface } from "../../Connexion/ConnexionModels";
|
||||||
import LL from "../../i18n/i18n-svelte";
|
import LL from "../../i18n/i18n-svelte";
|
||||||
|
|
||||||
@ -54,10 +54,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
//Quill
|
//Quill
|
||||||
onMount(async () => {
|
onMount(() => {
|
||||||
// Import quill
|
|
||||||
const { default: Quill } = await import("quill"); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
||||||
|
|
||||||
quill = new Quill(QUILL_EDITOR, {
|
quill = new Quill(QUILL_EDITOR, {
|
||||||
placeholder: $LL.menu.globalMessage.enter(),
|
placeholder: $LL.menu.globalMessage.enter(),
|
||||||
theme: "snow",
|
theme: "snow",
|
||||||
@ -76,3 +73,49 @@
|
|||||||
<section class="section-input-send-text">
|
<section class="section-input-send-text">
|
||||||
<div class="input-send-text" bind:this={QUILL_EDITOR} />
|
<div class="input-send-text" bind:this={QUILL_EDITOR} />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "../../../style/breakpoints.scss";
|
||||||
|
@import "quill/dist/quill.snow.css";
|
||||||
|
|
||||||
|
section.section-input-send-text {
|
||||||
|
--height-toolbar: 20%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
:global(.ql-toolbar) {
|
||||||
|
max-height: var(--height-toolbar);
|
||||||
|
background: whitesmoke;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.input-send-text {
|
||||||
|
height: calc(100% - var(--height-toolbar));
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
color: whitesmoke;
|
||||||
|
font-size: 1rem;
|
||||||
|
|
||||||
|
:global(.ql-editor.ql-blank::before) {
|
||||||
|
color: whitesmoke;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.ql-tooltip) {
|
||||||
|
top: 40% !important;
|
||||||
|
left: 20% !important;
|
||||||
|
|
||||||
|
color: whitesmoke;
|
||||||
|
background-color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
section.section-input-send-text {
|
||||||
|
--height-toolbar: 30%;
|
||||||
|
|
||||||
|
:global(.ql-toolbar) {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { localVolumeStore, obtainedMediaConstraintStore } from "../Stores/MediaStore";
|
import { localVolumeStore, obtainedMediaConstraintStore, silentStore } from "../Stores/MediaStore";
|
||||||
import { localStreamStore, isSilentStore } from "../Stores/MediaStore";
|
import { localStreamStore } from "../Stores/MediaStore";
|
||||||
import SoundMeterWidget from "./SoundMeterWidget.svelte";
|
import SoundMeterWidget from "./SoundMeterWidget.svelte";
|
||||||
import { onDestroy, onMount } from "svelte";
|
import { onDestroy, onMount } from "svelte";
|
||||||
import { srcObject } from "./Video/utils";
|
import { srcObject } from "./Video/utils";
|
||||||
@ -20,11 +20,6 @@
|
|||||||
unsubscribeLocalStreamStore();
|
unsubscribeLocalStreamStore();
|
||||||
});
|
});
|
||||||
|
|
||||||
let isSilent: boolean;
|
|
||||||
const unsubscribeIsSilent = isSilentStore.subscribe((value) => {
|
|
||||||
isSilent = value;
|
|
||||||
});
|
|
||||||
|
|
||||||
let cameraContainer: HTMLDivElement;
|
let cameraContainer: HTMLDivElement;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
@ -40,16 +35,14 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(unsubscribeIsSilent);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="nes-container is-rounded my-cam-video-container"
|
class="nes-container is-rounded my-cam-video-container"
|
||||||
class:hide={($localStreamStore.type !== "success" || !$obtainedMediaConstraintStore.video) && !isSilent}
|
class:hide={($localStreamStore.type !== "success" || !$obtainedMediaConstraintStore.video) && !$silentStore}
|
||||||
bind:this={cameraContainer}
|
bind:this={cameraContainer}
|
||||||
>
|
>
|
||||||
{#if isSilent}
|
{#if $silentStore}
|
||||||
<div class="is-silent">{$LL.camera.my.silentZone()}</div>
|
<div class="is-silent">{$LL.camera.my.silentZone()}</div>
|
||||||
{:else if $localStreamStore.type === "success" && $localStreamStore.stream}
|
{:else if $localStreamStore.type === "success" && $localStreamStore.stream}
|
||||||
<video class="my-cam-video" use:srcObject={stream} autoplay muted playsinline />
|
<video class="my-cam-video" use:srcObject={stream} autoplay muted playsinline />
|
||||||
|
4
front/src/Components/images/info.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="80" height="80" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M40 80C62.0914 80 80 62.0914 80 40C80 17.9086 62.0914 0 40 0C17.9086 0 0 17.9086 0 40C0 62.0914 17.9086 80 40 80ZM40 73C58.2254 73 73 58.2254 73 40C73 21.7746 58.2254 7 40 7C21.7746 7 7 21.7746 7 40C7 58.2254 21.7746 73 40 73Z" fill="white"/>
|
||||||
|
<path d="M43.7812 32.6406V58H37.1953V32.6406H43.7812ZM36.8906 26.0781C36.8906 25.0625 37.2109 24.2266 37.8516 23.5703C38.5078 22.8984 39.3828 22.5625 40.4766 22.5625C41.5859 22.5625 42.4609 22.8984 43.1016 23.5703C43.7422 24.2266 44.0625 25.0625 44.0625 26.0781C44.0625 27.0781 43.7344 27.9141 43.0781 28.5859C42.4375 29.2422 41.5781 29.5703 40.5 29.5703C39.3906 29.5703 38.5078 29.2422 37.8516 28.5859C37.2109 27.9141 36.8906 27.0781 36.8906 26.0781Z" fill="white"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 863 B |
@ -291,12 +291,12 @@ class ConnectionManager {
|
|||||||
);
|
);
|
||||||
|
|
||||||
connection.onConnectError((error: object) => {
|
connection.onConnectError((error: object) => {
|
||||||
console.log("An error occurred while connecting to socket server. Retrying");
|
console.log("onConnectError => An error occurred while connecting to socket server. Retrying");
|
||||||
reject(error);
|
reject(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.connectionErrorStream.subscribe((event: CloseEvent) => {
|
connection.connectionErrorStream.subscribe((event: CloseEvent) => {
|
||||||
console.log("An error occurred while connecting to socket server. Retrying");
|
console.log("connectionErrorStream => An error occurred while connecting to socket server. Retrying");
|
||||||
reject(
|
reject(
|
||||||
new Error(
|
new Error(
|
||||||
"An error occurred while connecting to socket server. Retrying. Code: " +
|
"An error occurred while connecting to socket server. Retrying. Code: " +
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
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 { AvailabilityStatus } from "../Messages/ts-proto-generated/protos/messages";
|
||||||
|
|
||||||
export interface PointInterface {
|
export interface PointInterface {
|
||||||
x: number;
|
x: number;
|
||||||
@ -14,7 +15,7 @@ export interface MessageUserPositionInterface {
|
|||||||
name: string;
|
name: string;
|
||||||
characterLayers: BodyResourceDescriptionInterface[];
|
characterLayers: BodyResourceDescriptionInterface[];
|
||||||
position: PointInterface;
|
position: PointInterface;
|
||||||
away: boolean;
|
status: AvailabilityStatus;
|
||||||
visitCardUrl: string | null;
|
visitCardUrl: string | null;
|
||||||
companion: string | null;
|
companion: string | null;
|
||||||
userUuid: string;
|
userUuid: string;
|
||||||
@ -30,7 +31,7 @@ export interface MessageUserJoined {
|
|||||||
name: string;
|
name: string;
|
||||||
characterLayers: BodyResourceDescriptionInterface[];
|
characterLayers: BodyResourceDescriptionInterface[];
|
||||||
position: PointInterface;
|
position: PointInterface;
|
||||||
away: boolean;
|
status: AvailabilityStatus;
|
||||||
visitCardUrl: string | null;
|
visitCardUrl: string | null;
|
||||||
companion: string | null;
|
companion: string | null;
|
||||||
userUuid: string;
|
userUuid: string;
|
||||||
|
@ -15,14 +15,9 @@ export interface RoomRedirect {
|
|||||||
|
|
||||||
export class Room {
|
export class Room {
|
||||||
public readonly id: string;
|
public readonly id: string;
|
||||||
/**
|
|
||||||
* @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;
|
||||||
private instance: string | undefined;
|
|
||||||
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;
|
||||||
@ -37,13 +32,6 @@ 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("_/") || this.id.startsWith("*/")) {
|
|
||||||
this.isPublic = true;
|
|
||||||
} else if (this.id.startsWith("@/")) {
|
|
||||||
this.isPublic = false;
|
|
||||||
} else {
|
|
||||||
throw new Error("Invalid room ID");
|
|
||||||
}
|
|
||||||
|
|
||||||
this._search = new URLSearchParams(roomUrl.search);
|
this._search = new URLSearchParams(roomUrl.search);
|
||||||
}
|
}
|
||||||
@ -84,8 +72,10 @@ export class Room {
|
|||||||
|
|
||||||
const currentRoom = new Room(baseUrl);
|
const currentRoom = new Room(baseUrl);
|
||||||
let instance: string = "global";
|
let instance: string = "global";
|
||||||
if (currentRoom.isPublic) {
|
if (currentRoom.id.startsWith("_/") || currentRoom.id.startsWith("*/")) {
|
||||||
instance = currentRoom.getInstance();
|
const match = /[_*]\/([^/]+)\/.+/.exec(currentRoom.id);
|
||||||
|
if (!match) throw new Error('Could not extract instance from "' + currentRoom.id + '"');
|
||||||
|
instance = match[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
baseUrl.pathname = "/_/" + instance + "/" + absoluteExitSceneUrl.host + absoluteExitSceneUrl.pathname;
|
baseUrl.pathname = "/_/" + instance + "/" + absoluteExitSceneUrl.host + absoluteExitSceneUrl.pathname;
|
||||||
@ -151,32 +141,6 @@ export class Room {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Instance name is:
|
|
||||||
* - In a public URL: the second part of the URL ( _/[instance]/map.json)
|
|
||||||
* - In a private URL: [organizationId/worldId]
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public getInstance(): string {
|
|
||||||
if (this.instance !== undefined) {
|
|
||||||
return this.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isPublic) {
|
|
||||||
const match = /[_*]\/([^/]+)\/.+/.exec(this.id);
|
|
||||||
if (!match) throw new Error('Could not extract instance from "' + this.id + '"');
|
|
||||||
this.instance = match[1];
|
|
||||||
return this.instance;
|
|
||||||
} else {
|
|
||||||
//const match = /@\/([^/]+)\/([^/]+)\/.+/.exec(this.id);
|
|
||||||
//if (!match) throw new Error('Could not extract instance from "' + this.id + '"');
|
|
||||||
//this.instance = match[1] + "/" + match[2];
|
|
||||||
this.instance = "";
|
|
||||||
return this.instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public isDisconnected(): boolean {
|
public isDisconnected(): boolean {
|
||||||
const alone = this._search.get("alone");
|
const alone = this._search.get("alone");
|
||||||
if (alone && alone !== "0" && alone.toLowerCase() !== "false") {
|
if (alone && alone !== "0" && alone.toLowerCase() !== "false") {
|
||||||
|
@ -41,6 +41,7 @@ import {
|
|||||||
SetPlayerDetailsMessage as SetPlayerDetailsMessageTsProto,
|
SetPlayerDetailsMessage as SetPlayerDetailsMessageTsProto,
|
||||||
PingMessage as PingMessageTsProto,
|
PingMessage as PingMessageTsProto,
|
||||||
CharacterLayerMessage,
|
CharacterLayerMessage,
|
||||||
|
AvailabilityStatus,
|
||||||
} from "../Messages/ts-proto-generated/protos/messages";
|
} from "../Messages/ts-proto-generated/protos/messages";
|
||||||
import { Subject } from "rxjs";
|
import { Subject } from "rxjs";
|
||||||
import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore";
|
import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore";
|
||||||
@ -520,9 +521,9 @@ export class RoomConnection implements RoomConnection {
|
|||||||
this.socket.send(bytes);
|
this.socket.send(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public emitPlayerAway(away: boolean): void {
|
public emitPlayerStatusChange(status: AvailabilityStatus): void {
|
||||||
const message = SetPlayerDetailsMessageTsProto.fromPartial({
|
const message = SetPlayerDetailsMessageTsProto.fromPartial({
|
||||||
away,
|
status,
|
||||||
});
|
});
|
||||||
const bytes = ClientToServerMessageTsProto.encode({
|
const bytes = ClientToServerMessageTsProto.encode({
|
||||||
message: {
|
message: {
|
||||||
@ -614,19 +615,6 @@ export class RoomConnection implements RoomConnection {
|
|||||||
this.socket.send(bytes);
|
this.socket.send(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setSilent(silent: boolean): void {
|
|
||||||
const bytes = ClientToServerMessageTsProto.encode({
|
|
||||||
message: {
|
|
||||||
$case: "silentMessage",
|
|
||||||
silentMessage: {
|
|
||||||
silent,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}).finish();
|
|
||||||
|
|
||||||
this.socket.send(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public setViewport(viewport: ViewportInterface): void {
|
public setViewport(viewport: ViewportInterface): void {
|
||||||
const bytes = ClientToServerMessageTsProto.encode({
|
const bytes = ClientToServerMessageTsProto.encode({
|
||||||
message: {
|
message: {
|
||||||
@ -670,7 +658,7 @@ export class RoomConnection implements RoomConnection {
|
|||||||
characterLayers,
|
characterLayers,
|
||||||
visitCardUrl: message.visitCardUrl,
|
visitCardUrl: message.visitCardUrl,
|
||||||
position: ProtobufClientUtils.toPointInterface(position),
|
position: ProtobufClientUtils.toPointInterface(position),
|
||||||
away: message.away,
|
status: message.status,
|
||||||
companion: companion ? companion.name : null,
|
companion: companion ? companion.name : null,
|
||||||
userUuid: message.userUuid,
|
userUuid: message.userUuid,
|
||||||
outlineColor: message.hasOutline ? message.outlineColor : undefined,
|
outlineColor: message.hasOutline ? message.outlineColor : undefined,
|
||||||
|
@ -23,6 +23,7 @@ export const DISPLAY_TERMS_OF_USE = getEnvConfig("DISPLAY_TERMS_OF_USE") == "tru
|
|||||||
export const NODE_ENV = getEnvConfig("NODE_ENV") || "development";
|
export const NODE_ENV = getEnvConfig("NODE_ENV") || "development";
|
||||||
export const CONTACT_URL = getEnvConfig("CONTACT_URL") || undefined;
|
export const CONTACT_URL = getEnvConfig("CONTACT_URL") || undefined;
|
||||||
export const PROFILE_URL = getEnvConfig("PROFILE_URL") || undefined;
|
export const PROFILE_URL = getEnvConfig("PROFILE_URL") || undefined;
|
||||||
|
export const IDENTITY_URL = getEnvConfig("IDENTITY_URL") || undefined;
|
||||||
export const POSTHOG_API_KEY: string = (getEnvConfig("POSTHOG_API_KEY") as string) || "";
|
export const POSTHOG_API_KEY: string = (getEnvConfig("POSTHOG_API_KEY") as string) || "";
|
||||||
export const POSTHOG_URL = getEnvConfig("POSTHOG_URL") || undefined;
|
export const POSTHOG_URL = getEnvConfig("POSTHOG_URL") || undefined;
|
||||||
export const DISABLE_ANONYMOUS: boolean = getEnvConfig("DISABLE_ANONYMOUS") === "true";
|
export const DISABLE_ANONYMOUS: boolean = getEnvConfig("DISABLE_ANONYMOUS") === "true";
|
||||||
|
@ -1,36 +1,41 @@
|
|||||||
|
import { AvailabilityStatus } from "../../Messages/ts-proto-generated/protos/messages";
|
||||||
import { Easing } from "../../types";
|
import { Easing } from "../../types";
|
||||||
|
|
||||||
export class PlayerStatusDot extends Phaser.GameObjects.Container {
|
export class PlayerStatusDot extends Phaser.GameObjects.Container {
|
||||||
private graphics: Phaser.GameObjects.Graphics;
|
private statusImage: Phaser.GameObjects.Image;
|
||||||
|
private statusImageOutline: Phaser.GameObjects.Image;
|
||||||
|
|
||||||
private away: boolean;
|
private status: AvailabilityStatus;
|
||||||
|
|
||||||
private readonly COLORS = {
|
private readonly COLORS: Record<AvailabilityStatus, { filling: number; outline: number }> = {
|
||||||
// online: 0x00ff00,
|
[AvailabilityStatus.AWAY]: { filling: 0xf5931e, outline: 0x875d13 },
|
||||||
// away: 0xffff00,
|
[AvailabilityStatus.ONLINE]: { filling: 0x8cc43f, outline: 0x427a25 },
|
||||||
online: 0x8cc43f,
|
[AvailabilityStatus.SILENT]: { filling: 0xe74c3c, outline: 0xc0392b },
|
||||||
onlineOutline: 0x427a25,
|
[AvailabilityStatus.JITSI]: { filling: 0x8cc43f, outline: 0x427a25 },
|
||||||
away: 0xf5931e,
|
[AvailabilityStatus.UNRECOGNIZED]: { filling: 0xffffff, outline: 0xffffff },
|
||||||
awayOutline: 0x875d13,
|
[AvailabilityStatus.UNCHANGED]: { filling: 0xffffff, outline: 0xffffff },
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(scene: Phaser.Scene, x: number, y: number) {
|
constructor(scene: Phaser.Scene, x: number, y: number) {
|
||||||
super(scene, x, y);
|
super(scene, x, y);
|
||||||
|
|
||||||
this.away = false;
|
this.status = AvailabilityStatus.ONLINE;
|
||||||
|
|
||||||
|
this.statusImage = this.scene.add.image(0, 0, "iconStatusIndicatorInside");
|
||||||
|
this.statusImageOutline = this.scene.add.image(0, 0, "iconStatusIndicatorOutline");
|
||||||
|
|
||||||
|
this.add([this.statusImage, this.statusImageOutline]);
|
||||||
|
|
||||||
this.graphics = this.scene.add.graphics();
|
|
||||||
this.add(this.graphics);
|
|
||||||
this.redraw();
|
this.redraw();
|
||||||
|
|
||||||
this.scene.add.existing(this);
|
this.scene.add.existing(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setAway(away: boolean = true, instant: boolean = false): void {
|
public setStatus(status: AvailabilityStatus, instant: boolean = false): void {
|
||||||
if (this.away === away) {
|
if (this.status === status || status === AvailabilityStatus.UNCHANGED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.away = away;
|
this.status = status;
|
||||||
if (instant) {
|
if (instant) {
|
||||||
this.redraw();
|
this.redraw();
|
||||||
} else {
|
} else {
|
||||||
@ -56,10 +61,8 @@ export class PlayerStatusDot extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private redraw(): void {
|
private redraw(): void {
|
||||||
this.graphics.clear();
|
const colors = this.COLORS[this.status];
|
||||||
this.graphics.fillStyle(this.away ? this.COLORS.away : this.COLORS.online);
|
this.statusImage.setTintFill(colors.filling);
|
||||||
this.graphics.lineStyle(1, this.away ? this.COLORS.awayOutline : this.COLORS.onlineOutline);
|
this.statusImageOutline.setTintFill(colors.outline);
|
||||||
this.graphics.fillCircle(0, 0, 3);
|
|
||||||
this.graphics.strokeCircle(0, 0, 3);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import { Companion } from "../Companion/Companion";
|
|||||||
import type { GameScene } from "../Game/GameScene";
|
import type { GameScene } from "../Game/GameScene";
|
||||||
import { DEPTH_INGAME_TEXT_INDEX } from "../Game/DepthIndexes";
|
import { DEPTH_INGAME_TEXT_INDEX } from "../Game/DepthIndexes";
|
||||||
import type OutlinePipelinePlugin from "phaser3-rex-plugins/plugins/outlinepipeline-plugin.js";
|
import type OutlinePipelinePlugin from "phaser3-rex-plugins/plugins/outlinepipeline-plugin.js";
|
||||||
import { isSilentStore } from "../../Stores/MediaStore";
|
|
||||||
import { lazyLoadPlayerCharacterTextures } from "./PlayerTexturesLoadingManager";
|
import { lazyLoadPlayerCharacterTextures } from "./PlayerTexturesLoadingManager";
|
||||||
import { TexturesHelper } from "../Helpers/TexturesHelper";
|
import { TexturesHelper } from "../Helpers/TexturesHelper";
|
||||||
import type { PictureStore } from "../../Stores/PictureStore";
|
import type { PictureStore } from "../../Stores/PictureStore";
|
||||||
@ -20,6 +19,7 @@ import type CancelablePromise from "cancelable-promise";
|
|||||||
import { TalkIcon } from "../Components/TalkIcon";
|
import { TalkIcon } from "../Components/TalkIcon";
|
||||||
import { Deferred } from "ts-deferred";
|
import { Deferred } from "ts-deferred";
|
||||||
import { PlayerStatusDot } from "../Components/PlayerStatusDot";
|
import { PlayerStatusDot } from "../Components/PlayerStatusDot";
|
||||||
|
import { AvailabilityStatus } from "../../Messages/ts-proto-generated/protos/messages";
|
||||||
|
|
||||||
const playerNameY = -25;
|
const playerNameY = -25;
|
||||||
const interactiveRadius = 35;
|
const interactiveRadius = 35;
|
||||||
@ -236,8 +236,8 @@ export abstract class Character extends Container implements OutlineableInterfac
|
|||||||
this.talkIcon.show(show, forceClose);
|
this.talkIcon.show(show, forceClose);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setAwayStatus(away: boolean = true, instant: boolean = false): void {
|
public setStatus(status: AvailabilityStatus, instant: boolean = false): void {
|
||||||
this.statusDot.setAway(away, instant);
|
this.statusDot.setStatus(status, instant);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addCompanion(name: string, texturePromise?: CancelablePromise<string>): void {
|
public addCompanion(name: string, texturePromise?: CancelablePromise<string>): void {
|
||||||
@ -355,13 +355,6 @@ export abstract class Character extends Container implements OutlineableInterfac
|
|||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
isSilent() {
|
|
||||||
isSilentStore.set(true);
|
|
||||||
}
|
|
||||||
noSilent() {
|
|
||||||
isSilentStore.set(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
playEmote(emote: string) {
|
playEmote(emote: string) {
|
||||||
this.cancelPreviousEmote();
|
this.cancelPreviousEmote();
|
||||||
const emoteY = -45;
|
const emoteY = -45;
|
||||||
|
@ -22,9 +22,9 @@ export type layerChangeCallback = (
|
|||||||
allLayersOnNewPosition: Array<ITiledMapLayer>
|
allLayersOnNewPosition: Array<ITiledMapLayer>
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
export type zoneChangeCallback = (
|
export type areaChangeCallback = (
|
||||||
zonesChangedByAction: Array<ITiledMapObject>,
|
areasChangedByAction: Array<ITiledMapObject>,
|
||||||
allZonesOnNewPosition: Array<ITiledMapObject>
|
allAreasOnNewPosition: Array<ITiledMapObject>
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,8 +54,8 @@ export class GameMap {
|
|||||||
|
|
||||||
private enterLayerCallbacks = Array<layerChangeCallback>();
|
private enterLayerCallbacks = Array<layerChangeCallback>();
|
||||||
private leaveLayerCallbacks = Array<layerChangeCallback>();
|
private leaveLayerCallbacks = Array<layerChangeCallback>();
|
||||||
private enterZoneCallbacks = Array<zoneChangeCallback>();
|
private enterAreaCallbacks = Array<areaChangeCallback>();
|
||||||
private leaveZoneCallbacks = Array<zoneChangeCallback>();
|
private leaveAreaCallbacks = Array<areaChangeCallback>();
|
||||||
|
|
||||||
private tileNameMap = new Map<string, number>();
|
private tileNameMap = new Map<string, number>();
|
||||||
|
|
||||||
@ -63,7 +63,9 @@ export class GameMap {
|
|||||||
public readonly flatLayers: ITiledMapLayer[];
|
public readonly flatLayers: ITiledMapLayer[];
|
||||||
public readonly tiledObjects: ITiledMapObject[];
|
public readonly tiledObjects: ITiledMapObject[];
|
||||||
public readonly phaserLayers: TilemapLayer[] = [];
|
public readonly phaserLayers: TilemapLayer[] = [];
|
||||||
public readonly zones: ITiledMapObject[] = [];
|
public readonly areas: ITiledMapObject[] = [];
|
||||||
|
|
||||||
|
private readonly areasPositionOffsetY: number = 16;
|
||||||
|
|
||||||
public exitUrls: Array<string> = [];
|
public exitUrls: Array<string> = [];
|
||||||
|
|
||||||
@ -76,7 +78,8 @@ export class GameMap {
|
|||||||
) {
|
) {
|
||||||
this.flatLayers = flattenGroupLayersMap(map);
|
this.flatLayers = flattenGroupLayersMap(map);
|
||||||
this.tiledObjects = this.getObjectsFromLayers(this.flatLayers);
|
this.tiledObjects = this.getObjectsFromLayers(this.flatLayers);
|
||||||
this.zones = this.tiledObjects.filter((object) => object.type === "zone");
|
// NOTE: We leave "zone" for legacy reasons
|
||||||
|
this.areas = this.tiledObjects.filter((object) => ["zone", "area"].includes(object.type));
|
||||||
|
|
||||||
let depth = -2;
|
let depth = -2;
|
||||||
for (const layer of this.flatLayers) {
|
for (const layer of this.flatLayers) {
|
||||||
@ -148,7 +151,10 @@ export class GameMap {
|
|||||||
public setPosition(x: number, y: number) {
|
public setPosition(x: number, y: number) {
|
||||||
this.oldPosition = this.position;
|
this.oldPosition = this.position;
|
||||||
this.position = { x, y };
|
this.position = { x, y };
|
||||||
this.triggerZonesChange();
|
const areasChanged = this.triggerAreasChange();
|
||||||
|
if (areasChanged) {
|
||||||
|
this.triggerAllProperties();
|
||||||
|
}
|
||||||
|
|
||||||
this.oldKey = this.key;
|
this.oldKey = this.key;
|
||||||
|
|
||||||
@ -201,21 +207,17 @@ export class GameMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a callback called when the user moves inside another zone.
|
* Registers a callback called when the user moves inside another area.
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
public onEnterZone(callback: zoneChangeCallback) {
|
public onEnterArea(callback: areaChangeCallback) {
|
||||||
this.enterZoneCallbacks.push(callback);
|
this.enterAreaCallbacks.push(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a callback called when the user moves outside another zone.
|
* Registers a callback called when the user moves outside another area.
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
*/
|
||||||
public onLeaveZone(callback: zoneChangeCallback) {
|
public onLeaveArea(callback: areaChangeCallback) {
|
||||||
this.leaveZoneCallbacks.push(callback);
|
this.leaveAreaCallbacks.push(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public findLayer(layerName: string): ITiledMapLayer | undefined {
|
public findLayer(layerName: string): ITiledMapLayer | undefined {
|
||||||
@ -437,55 +439,56 @@ export class GameMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We use Tiled Objects with type "zone" as zones with defined x, y, width and height for easier event triggering.
|
* We use Tiled Objects with type "area" as areas with defined x, y, width and height for easier event triggering.
|
||||||
|
* @returns If there were any areas changes
|
||||||
*/
|
*/
|
||||||
private triggerZonesChange(): void {
|
private triggerAreasChange(): boolean {
|
||||||
const zonesByOldPosition = this.oldPosition
|
const areasByOldPosition = this.getAreasOnPosition(this.oldPosition, this.areasPositionOffsetY);
|
||||||
? this.zones.filter((zone) => {
|
const areasByNewPosition = this.getAreasOnPosition(this.position, this.areasPositionOffsetY);
|
||||||
if (!this.oldPosition) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return MathUtils.isOverlappingWithRectangle(this.oldPosition, zone);
|
|
||||||
})
|
|
||||||
: [];
|
|
||||||
|
|
||||||
const zonesByNewPosition = this.position
|
const enterAreas = new Set(areasByNewPosition);
|
||||||
? this.zones.filter((zone) => {
|
const leaveAreas = new Set(areasByOldPosition);
|
||||||
if (!this.position) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return MathUtils.isOverlappingWithRectangle(this.position, zone);
|
|
||||||
})
|
|
||||||
: [];
|
|
||||||
|
|
||||||
const enterZones = new Set(zonesByNewPosition);
|
enterAreas.forEach((area) => {
|
||||||
const leaveZones = new Set(zonesByOldPosition);
|
if (leaveAreas.has(area)) {
|
||||||
|
leaveAreas.delete(area);
|
||||||
enterZones.forEach((zone) => {
|
enterAreas.delete(area);
|
||||||
if (leaveZones.has(zone)) {
|
|
||||||
leaveZones.delete(zone);
|
|
||||||
enterZones.delete(zone);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (enterZones.size > 0) {
|
let areasChange = false;
|
||||||
const zonesArray = Array.from(enterZones);
|
if (enterAreas.size > 0) {
|
||||||
for (const callback of this.enterZoneCallbacks) {
|
const areasArray = Array.from(enterAreas);
|
||||||
callback(zonesArray, zonesByNewPosition);
|
for (const callback of this.enterAreaCallbacks) {
|
||||||
|
callback(areasArray, areasByNewPosition);
|
||||||
}
|
}
|
||||||
|
areasChange = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (leaveZones.size > 0) {
|
if (leaveAreas.size > 0) {
|
||||||
const zonesArray = Array.from(leaveZones);
|
const areasArray = Array.from(leaveAreas);
|
||||||
for (const callback of this.leaveZoneCallbacks) {
|
for (const callback of this.leaveAreaCallbacks) {
|
||||||
callback(zonesArray, zonesByNewPosition);
|
callback(areasArray, areasByNewPosition);
|
||||||
}
|
}
|
||||||
|
areasChange = true;
|
||||||
}
|
}
|
||||||
|
return areasChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getProperties(key: number): Map<string, string | boolean | number> {
|
private getProperties(key: number): Map<string, string | boolean | number> {
|
||||||
const properties = new Map<string, string | boolean | number>();
|
const properties = new Map<string, string | boolean | number>();
|
||||||
|
|
||||||
|
for (const area of this.getAreasOnPosition(this.position, this.areasPositionOffsetY)) {
|
||||||
|
if (area.properties !== undefined) {
|
||||||
|
for (const property of area.properties) {
|
||||||
|
if (property.value === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
properties.set(property.name, property.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const layer of this.flatLayers) {
|
for (const layer of this.flatLayers) {
|
||||||
if (layer.type !== "tilelayer") {
|
if (layer.type !== "tilelayer") {
|
||||||
continue;
|
continue;
|
||||||
@ -524,6 +527,17 @@ export class GameMap {
|
|||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getAreasOnPosition(position?: { x: number; y: number }, offsetY: number = 0): ITiledMapObject[] {
|
||||||
|
return position
|
||||||
|
? this.areas.filter((area) => {
|
||||||
|
if (!position) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return MathUtils.isOverlappingWithRectangle({ x: position.x, y: position.y + offsetY }, area);
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
|
||||||
private getTileProperty(index: number): Array<ITiledMapProperty> {
|
private getTileProperty(index: number): Array<ITiledMapProperty> {
|
||||||
if (this.tileSetPropertyMap[index]) {
|
if (this.tileSetPropertyMap[index]) {
|
||||||
return this.tileSetPropertyMap[index];
|
return this.tileSetPropertyMap[index];
|
||||||
|
@ -7,6 +7,7 @@ export enum GameMapProperties {
|
|||||||
EXIT_URL = "exitUrl",
|
EXIT_URL = "exitUrl",
|
||||||
EXIT_SCENE_URL = "exitSceneUrl",
|
EXIT_SCENE_URL = "exitSceneUrl",
|
||||||
FONT_FAMILY = "font-family",
|
FONT_FAMILY = "font-family",
|
||||||
|
FOCUSABLE = "focusable",
|
||||||
JITSI_ADMIN_ROOM_TAG = "jitsiRoomAdminTag",
|
JITSI_ADMIN_ROOM_TAG = "jitsiRoomAdminTag",
|
||||||
JITSI_CONFIG = "jitsiConfig",
|
JITSI_CONFIG = "jitsiConfig",
|
||||||
JITSI_INTERFACE_CONFIG = "jitsiInterfaceConfig",
|
JITSI_INTERFACE_CONFIG = "jitsiInterfaceConfig",
|
||||||
@ -15,6 +16,7 @@ export enum GameMapProperties {
|
|||||||
JITSI_TRIGGER_MESSAGE = "jitsiTriggerMessage",
|
JITSI_TRIGGER_MESSAGE = "jitsiTriggerMessage",
|
||||||
JITSI_URL = "jitsiUrl",
|
JITSI_URL = "jitsiUrl",
|
||||||
JITSI_WIDTH = "jitsiWidth",
|
JITSI_WIDTH = "jitsiWidth",
|
||||||
|
JITSI_NO_PREFIX = "jitsiNoPrefix",
|
||||||
NAME = "name",
|
NAME = "name",
|
||||||
OPEN_TAB = "openTab",
|
OPEN_TAB = "openTab",
|
||||||
OPEN_WEBSITE = "openWebsite",
|
OPEN_WEBSITE = "openWebsite",
|
||||||
@ -36,4 +38,5 @@ export enum GameMapProperties {
|
|||||||
URL = "url",
|
URL = "url",
|
||||||
WRITABLE_BY = "writableBy",
|
WRITABLE_BY = "writableBy",
|
||||||
ZONE = "zone",
|
ZONE = "zone",
|
||||||
|
ZOOM_MARGIN = "zoom_margin",
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore";
|
|||||||
import { localUserStore } from "../../Connexion/LocalUserStore";
|
import { localUserStore } from "../../Connexion/LocalUserStore";
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
import { ON_ACTION_TRIGGER_BUTTON, ON_ICON_TRIGGER_BUTTON } from "../../WebRtc/LayoutManager";
|
import { ON_ACTION_TRIGGER_BUTTON, ON_ICON_TRIGGER_BUTTON } from "../../WebRtc/LayoutManager";
|
||||||
import type { ITiledMapLayer } from "../Map/ITiledMap";
|
import type { ITiledMapProperty } from "../Map/ITiledMap";
|
||||||
import { GameMapProperties } from "./GameMapProperties";
|
import { GameMapProperties } from "./GameMapProperties";
|
||||||
import type { CoWebsite } from "../../WebRtc/CoWebsite/CoWesbite";
|
import type { CoWebsite } from "../../WebRtc/CoWebsite/CoWesbite";
|
||||||
import { SimpleCoWebsite } from "../../WebRtc/CoWebsite/SimpleCoWebsite";
|
import { SimpleCoWebsite } from "../../WebRtc/CoWebsite/SimpleCoWebsite";
|
||||||
@ -17,15 +17,28 @@ import { audioManagerFileStore, audioManagerVisibilityStore } from "../../Stores
|
|||||||
import { iframeListener } from "../../Api/IframeListener";
|
import { iframeListener } from "../../Api/IframeListener";
|
||||||
import { Room } from "../../Connexion/Room";
|
import { Room } from "../../Connexion/Room";
|
||||||
import LL from "../../i18n/i18n-svelte";
|
import LL from "../../i18n/i18n-svelte";
|
||||||
|
import { inJitsiStore, silentStore } from "../../Stores/MediaStore";
|
||||||
|
|
||||||
interface OpenCoWebsite {
|
interface OpenCoWebsite {
|
||||||
actionId: string;
|
actionId: string;
|
||||||
coWebsite?: CoWebsite;
|
coWebsite?: CoWebsite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Either Layer or Object within Objects Layer in Tiled
|
||||||
|
*/
|
||||||
|
export interface ITiledPlace {
|
||||||
|
name: string;
|
||||||
|
properties?: ITiledMapProperty[];
|
||||||
|
x?: number;
|
||||||
|
y?: number;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class GameMapPropertiesListener {
|
export class GameMapPropertiesListener {
|
||||||
private coWebsitesOpenByLayer = new Map<ITiledMapLayer, OpenCoWebsite>();
|
private coWebsitesOpenByPlace = new Map<ITiledPlace, OpenCoWebsite>();
|
||||||
private coWebsitesActionTriggerByLayer = new Map<ITiledMapLayer, string>();
|
private coWebsitesActionTriggerByPlace = new Map<ITiledPlace, string>();
|
||||||
|
|
||||||
constructor(private scene: GameScene, private gameMap: GameMap) {}
|
constructor(private scene: GameScene, private gameMap: GameMap) {}
|
||||||
|
|
||||||
@ -65,9 +78,14 @@ export class GameMapPropertiesListener {
|
|||||||
coWebsiteManager.closeCoWebsite(coWebsite);
|
coWebsiteManager.closeCoWebsite(coWebsite);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
inJitsiStore.set(false);
|
||||||
} else {
|
} else {
|
||||||
const openJitsiRoomFunction = () => {
|
const openJitsiRoomFunction = () => {
|
||||||
const roomName = jitsiFactory.getRoomName(newValue.toString(), this.scene.instance);
|
let addPrefix = true;
|
||||||
|
if (allProps.get(GameMapProperties.JITSI_NO_PREFIX)) {
|
||||||
|
addPrefix = false;
|
||||||
|
}
|
||||||
|
const roomName = jitsiFactory.getRoomName(newValue.toString(), this.scene.roomUrl, addPrefix);
|
||||||
const jitsiUrl = allProps.get(GameMapProperties.JITSI_URL) as string | undefined;
|
const jitsiUrl = allProps.get(GameMapProperties.JITSI_URL) as string | undefined;
|
||||||
|
|
||||||
if (JITSI_PRIVATE_MODE && !jitsiUrl) {
|
if (JITSI_PRIVATE_MODE && !jitsiUrl) {
|
||||||
@ -103,11 +121,15 @@ export class GameMapPropertiesListener {
|
|||||||
uuid: "jitsi",
|
uuid: "jitsi",
|
||||||
type: "message",
|
type: "message",
|
||||||
message: message,
|
message: message,
|
||||||
callback: () => openJitsiRoomFunction(),
|
callback: () => {
|
||||||
|
openJitsiRoomFunction();
|
||||||
|
inJitsiStore.set(true);
|
||||||
|
},
|
||||||
userInputManager: this.scene.userInputManager,
|
userInputManager: this.scene.userInputManager,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
openJitsiRoomFunction();
|
openJitsiRoomFunction();
|
||||||
|
inJitsiStore.set(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -144,11 +166,9 @@ export class GameMapPropertiesListener {
|
|||||||
|
|
||||||
this.gameMap.onPropertyChange(GameMapProperties.SILENT, (newValue) => {
|
this.gameMap.onPropertyChange(GameMapProperties.SILENT, (newValue) => {
|
||||||
if (newValue === undefined || newValue === false || newValue === "") {
|
if (newValue === undefined || newValue === false || newValue === "") {
|
||||||
this.scene.connection?.setSilent(false);
|
silentStore.set(false);
|
||||||
this.scene.CurrentPlayer.noSilent();
|
|
||||||
} else {
|
} else {
|
||||||
this.scene.connection?.setSilent(true);
|
silentStore.set(true);
|
||||||
this.scene.CurrentPlayer.isSilent();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -179,199 +199,247 @@ export class GameMapPropertiesListener {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Open a new co-website by the property.
|
|
||||||
this.gameMap.onEnterLayer((newLayers) => {
|
this.gameMap.onEnterLayer((newLayers) => {
|
||||||
const handler = () => {
|
this.onEnterPlaceHandler(newLayers);
|
||||||
newLayers.forEach((layer) => {
|
|
||||||
if (!layer.properties) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let openWebsiteProperty: string | undefined;
|
|
||||||
let allowApiProperty: boolean | undefined;
|
|
||||||
let websitePolicyProperty: string | undefined;
|
|
||||||
let websiteWidthProperty: number | undefined;
|
|
||||||
let websitePositionProperty: number | undefined;
|
|
||||||
let websiteTriggerProperty: string | undefined;
|
|
||||||
let websiteTriggerMessageProperty: string | undefined;
|
|
||||||
let websiteHintProperty: string | undefined;
|
|
||||||
|
|
||||||
layer.properties.forEach((property) => {
|
|
||||||
switch (property.name) {
|
|
||||||
case GameMapProperties.OPEN_WEBSITE:
|
|
||||||
openWebsiteProperty = property.value as string | undefined;
|
|
||||||
break;
|
|
||||||
case GameMapProperties.OPEN_WEBSITE_ALLOW_API:
|
|
||||||
allowApiProperty = property.value as boolean | undefined;
|
|
||||||
break;
|
|
||||||
case GameMapProperties.OPEN_WEBSITE_POLICY:
|
|
||||||
websitePolicyProperty = property.value as string | undefined;
|
|
||||||
break;
|
|
||||||
case GameMapProperties.OPEN_WEBSITE_WIDTH:
|
|
||||||
websiteWidthProperty = property.value as number | undefined;
|
|
||||||
break;
|
|
||||||
case GameMapProperties.OPEN_WEBSITE_POSITION:
|
|
||||||
websitePositionProperty = property.value as number | undefined;
|
|
||||||
break;
|
|
||||||
case GameMapProperties.OPEN_WEBSITE_TRIGGER:
|
|
||||||
websiteTriggerProperty = property.value as string | undefined;
|
|
||||||
break;
|
|
||||||
case GameMapProperties.OPEN_WEBSITE_TRIGGER_MESSAGE:
|
|
||||||
websiteTriggerMessageProperty = property.value as string | undefined;
|
|
||||||
break;
|
|
||||||
case GameMapProperties.OPEN_WEBSITE_HINT:
|
|
||||||
websiteHintProperty = property.value as string | undefined;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!openWebsiteProperty) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const actionId = "openWebsite-" + (Math.random() + 1).toString(36).substring(7);
|
|
||||||
|
|
||||||
if (this.coWebsitesOpenByLayer.has(layer)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const coWebsiteOpen: OpenCoWebsite = {
|
|
||||||
actionId: actionId,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.coWebsitesOpenByLayer.set(layer, coWebsiteOpen);
|
|
||||||
|
|
||||||
const loadCoWebsiteFunction = (coWebsite: CoWebsite) => {
|
|
||||||
coWebsiteManager.loadCoWebsite(coWebsite).catch(() => {
|
|
||||||
console.error("Error during loading a co-website: " + coWebsite.getUrl());
|
|
||||||
});
|
|
||||||
|
|
||||||
layoutManagerActionStore.removeAction(actionId);
|
|
||||||
};
|
|
||||||
|
|
||||||
const openCoWebsiteFunction = () => {
|
|
||||||
const coWebsite = new SimpleCoWebsite(
|
|
||||||
new URL(openWebsiteProperty ?? "", this.scene.MapUrlFile),
|
|
||||||
allowApiProperty,
|
|
||||||
websitePolicyProperty,
|
|
||||||
websiteWidthProperty,
|
|
||||||
false,
|
|
||||||
websiteHintProperty
|
|
||||||
);
|
|
||||||
|
|
||||||
coWebsiteOpen.coWebsite = coWebsite;
|
|
||||||
|
|
||||||
coWebsiteManager.addCoWebsiteToStore(coWebsite, websitePositionProperty);
|
|
||||||
|
|
||||||
loadCoWebsiteFunction(coWebsite);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (
|
|
||||||
localUserStore.getForceCowebsiteTrigger() ||
|
|
||||||
websiteTriggerProperty === ON_ACTION_TRIGGER_BUTTON
|
|
||||||
) {
|
|
||||||
if (!websiteTriggerMessageProperty) {
|
|
||||||
websiteTriggerMessageProperty = get(LL).trigger.cowebsite();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.coWebsitesActionTriggerByLayer.set(layer, actionId);
|
|
||||||
|
|
||||||
layoutManagerActionStore.addAction({
|
|
||||||
uuid: actionId,
|
|
||||||
type: "message",
|
|
||||||
message: websiteTriggerMessageProperty,
|
|
||||||
callback: () => openCoWebsiteFunction(),
|
|
||||||
userInputManager: this.scene.userInputManager,
|
|
||||||
});
|
|
||||||
} else if (websiteTriggerProperty === ON_ICON_TRIGGER_BUTTON) {
|
|
||||||
const coWebsite = new SimpleCoWebsite(
|
|
||||||
new URL(openWebsiteProperty ?? "", this.scene.MapUrlFile),
|
|
||||||
allowApiProperty,
|
|
||||||
websitePolicyProperty,
|
|
||||||
websiteWidthProperty,
|
|
||||||
false,
|
|
||||||
websiteHintProperty
|
|
||||||
);
|
|
||||||
|
|
||||||
coWebsiteOpen.coWebsite = coWebsite;
|
|
||||||
|
|
||||||
coWebsiteManager.addCoWebsiteToStore(coWebsite, websitePositionProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!websiteTriggerProperty) {
|
|
||||||
openCoWebsiteFunction();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handler();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Close opened co-websites on leave the layer who contain the property.
|
|
||||||
this.gameMap.onLeaveLayer((oldLayers) => {
|
this.gameMap.onLeaveLayer((oldLayers) => {
|
||||||
const handler = () => {
|
this.onLeavePlaceHandler(oldLayers);
|
||||||
oldLayers.forEach((layer) => {
|
});
|
||||||
if (!layer.properties) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let openWebsiteProperty: string | undefined;
|
this.gameMap.onEnterArea((newAreas) => {
|
||||||
let websiteTriggerProperty: string | undefined;
|
this.onEnterPlaceHandler(newAreas);
|
||||||
|
});
|
||||||
|
|
||||||
layer.properties.forEach((property) => {
|
this.gameMap.onLeaveArea((oldAreas) => {
|
||||||
switch (property.name) {
|
this.onLeavePlaceHandler(oldAreas);
|
||||||
case GameMapProperties.OPEN_WEBSITE:
|
|
||||||
openWebsiteProperty = property.value as string | undefined;
|
|
||||||
break;
|
|
||||||
case GameMapProperties.OPEN_WEBSITE_TRIGGER:
|
|
||||||
websiteTriggerProperty = property.value as string | undefined;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!openWebsiteProperty) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const coWebsiteOpen = this.coWebsitesOpenByLayer.get(layer);
|
|
||||||
|
|
||||||
if (!coWebsiteOpen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const coWebsite = coWebsiteOpen.coWebsite;
|
|
||||||
|
|
||||||
if (coWebsite) {
|
|
||||||
coWebsiteManager.closeCoWebsite(coWebsite);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.coWebsitesOpenByLayer.delete(layer);
|
|
||||||
|
|
||||||
if (!websiteTriggerProperty) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const actionStore = get(layoutManagerActionStore);
|
|
||||||
const actionTriggerUuid = this.coWebsitesActionTriggerByLayer.get(layer);
|
|
||||||
|
|
||||||
if (!actionTriggerUuid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const action =
|
|
||||||
actionStore && actionStore.length > 0
|
|
||||||
? actionStore.find((action) => action.uuid === actionTriggerUuid)
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
if (action) {
|
|
||||||
layoutManagerActionStore.removeAction(actionTriggerUuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.coWebsitesActionTriggerByLayer.delete(layer);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handler();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onEnterPlaceHandler(places: ITiledPlace[]): void {
|
||||||
|
places.forEach((place) => {
|
||||||
|
this.handleOpenWebsitePropertiesOnEnter(place);
|
||||||
|
this.handleFocusablePropertiesOnEnter(place);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private onLeavePlaceHandler(places: ITiledPlace[]): void {
|
||||||
|
places.forEach((place) => {
|
||||||
|
if (!place.properties) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handleOpenWebsitePropertiesOnLeave(place);
|
||||||
|
this.handleFocusablePropertiesOnLeave(place);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleOpenWebsitePropertiesOnEnter(place: ITiledPlace): void {
|
||||||
|
if (!place.properties) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let openWebsiteProperty: string | undefined;
|
||||||
|
let allowApiProperty: boolean | undefined;
|
||||||
|
let websitePolicyProperty: string | undefined;
|
||||||
|
let websiteWidthProperty: number | undefined;
|
||||||
|
let websitePositionProperty: number | undefined;
|
||||||
|
let websiteTriggerProperty: string | undefined;
|
||||||
|
let websiteTriggerMessageProperty: string | undefined;
|
||||||
|
let websiteHintProperty: string | undefined;
|
||||||
|
|
||||||
|
place.properties.forEach((property) => {
|
||||||
|
switch (property.name) {
|
||||||
|
case GameMapProperties.OPEN_WEBSITE:
|
||||||
|
openWebsiteProperty = property.value as string | undefined;
|
||||||
|
break;
|
||||||
|
case GameMapProperties.OPEN_WEBSITE_ALLOW_API:
|
||||||
|
allowApiProperty = property.value as boolean | undefined;
|
||||||
|
break;
|
||||||
|
case GameMapProperties.OPEN_WEBSITE_POLICY:
|
||||||
|
websitePolicyProperty = property.value as string | undefined;
|
||||||
|
break;
|
||||||
|
case GameMapProperties.OPEN_WEBSITE_WIDTH:
|
||||||
|
websiteWidthProperty = property.value as number | undefined;
|
||||||
|
break;
|
||||||
|
case GameMapProperties.OPEN_WEBSITE_POSITION:
|
||||||
|
websitePositionProperty = property.value as number | undefined;
|
||||||
|
break;
|
||||||
|
case GameMapProperties.OPEN_WEBSITE_TRIGGER:
|
||||||
|
websiteTriggerProperty = property.value as string | undefined;
|
||||||
|
break;
|
||||||
|
case GameMapProperties.OPEN_WEBSITE_TRIGGER_MESSAGE:
|
||||||
|
websiteTriggerMessageProperty = property.value as string | undefined;
|
||||||
|
break;
|
||||||
|
case GameMapProperties.OPEN_WEBSITE_HINT:
|
||||||
|
websiteHintProperty = property.value as string | undefined;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!openWebsiteProperty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const actionId = "openWebsite-" + (Math.random() + 1).toString(36).substring(7);
|
||||||
|
|
||||||
|
if (this.coWebsitesOpenByPlace.has(place)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const coWebsiteOpen: OpenCoWebsite = {
|
||||||
|
actionId: actionId,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.coWebsitesOpenByPlace.set(place, coWebsiteOpen);
|
||||||
|
|
||||||
|
const loadCoWebsiteFunction = (coWebsite: CoWebsite) => {
|
||||||
|
coWebsiteManager.loadCoWebsite(coWebsite).catch(() => {
|
||||||
|
console.error("Error during loading a co-website: " + coWebsite.getUrl());
|
||||||
|
});
|
||||||
|
|
||||||
|
layoutManagerActionStore.removeAction(actionId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const openCoWebsiteFunction = () => {
|
||||||
|
const coWebsite = new SimpleCoWebsite(
|
||||||
|
new URL(openWebsiteProperty ?? "", this.scene.MapUrlFile),
|
||||||
|
allowApiProperty,
|
||||||
|
websitePolicyProperty,
|
||||||
|
websiteWidthProperty,
|
||||||
|
false,
|
||||||
|
websiteHintProperty
|
||||||
|
);
|
||||||
|
|
||||||
|
coWebsiteOpen.coWebsite = coWebsite;
|
||||||
|
|
||||||
|
coWebsiteManager.addCoWebsiteToStore(coWebsite, websitePositionProperty);
|
||||||
|
|
||||||
|
loadCoWebsiteFunction(coWebsite);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (localUserStore.getForceCowebsiteTrigger() || websiteTriggerProperty === ON_ACTION_TRIGGER_BUTTON) {
|
||||||
|
if (!websiteTriggerMessageProperty) {
|
||||||
|
websiteTriggerMessageProperty = get(LL).trigger.cowebsite();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.coWebsitesActionTriggerByPlace.set(place, actionId);
|
||||||
|
|
||||||
|
layoutManagerActionStore.addAction({
|
||||||
|
uuid: actionId,
|
||||||
|
type: "message",
|
||||||
|
message: websiteTriggerMessageProperty,
|
||||||
|
callback: () => openCoWebsiteFunction(),
|
||||||
|
userInputManager: this.scene.userInputManager,
|
||||||
|
});
|
||||||
|
} else if (websiteTriggerProperty === ON_ICON_TRIGGER_BUTTON) {
|
||||||
|
const coWebsite = new SimpleCoWebsite(
|
||||||
|
new URL(openWebsiteProperty ?? "", this.scene.MapUrlFile),
|
||||||
|
allowApiProperty,
|
||||||
|
websitePolicyProperty,
|
||||||
|
websiteWidthProperty,
|
||||||
|
false,
|
||||||
|
websiteHintProperty
|
||||||
|
);
|
||||||
|
|
||||||
|
coWebsiteOpen.coWebsite = coWebsite;
|
||||||
|
|
||||||
|
coWebsiteManager.addCoWebsiteToStore(coWebsite, websitePositionProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!websiteTriggerProperty) {
|
||||||
|
openCoWebsiteFunction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleFocusablePropertiesOnEnter(place: ITiledPlace): void {
|
||||||
|
if (!place.properties) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (place.x === undefined || place.y === undefined || !place.height || !place.width) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const focusable = place.properties.find((property) => property.name === GameMapProperties.FOCUSABLE);
|
||||||
|
if (focusable && focusable.value === true) {
|
||||||
|
const zoomMargin = place.properties.find((property) => property.name === GameMapProperties.ZOOM_MARGIN);
|
||||||
|
this.scene.getCameraManager().enterFocusMode(
|
||||||
|
{
|
||||||
|
x: place.x + place.width * 0.5,
|
||||||
|
y: place.y + place.height * 0.5,
|
||||||
|
width: place.width,
|
||||||
|
height: place.height,
|
||||||
|
},
|
||||||
|
zoomMargin ? Math.max(0, Number(zoomMargin.value)) : undefined
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleOpenWebsitePropertiesOnLeave(place: ITiledPlace): void {
|
||||||
|
if (!place.properties) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let openWebsiteProperty: string | undefined;
|
||||||
|
let websiteTriggerProperty: string | undefined;
|
||||||
|
|
||||||
|
place.properties.forEach((property) => {
|
||||||
|
switch (property.name) {
|
||||||
|
case GameMapProperties.OPEN_WEBSITE:
|
||||||
|
openWebsiteProperty = property.value as string | undefined;
|
||||||
|
break;
|
||||||
|
case GameMapProperties.OPEN_WEBSITE_TRIGGER:
|
||||||
|
websiteTriggerProperty = property.value as string | undefined;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!openWebsiteProperty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const coWebsiteOpen = this.coWebsitesOpenByPlace.get(place);
|
||||||
|
|
||||||
|
if (!coWebsiteOpen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const coWebsite = coWebsiteOpen.coWebsite;
|
||||||
|
|
||||||
|
if (coWebsite) {
|
||||||
|
coWebsiteManager.closeCoWebsite(coWebsite);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.coWebsitesOpenByPlace.delete(place);
|
||||||
|
|
||||||
|
if (!websiteTriggerProperty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const actionStore = get(layoutManagerActionStore);
|
||||||
|
const actionTriggerUuid = this.coWebsitesActionTriggerByPlace.get(place);
|
||||||
|
|
||||||
|
if (!actionTriggerUuid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const action =
|
||||||
|
actionStore && actionStore.length > 0
|
||||||
|
? actionStore.find((action) => action.uuid === actionTriggerUuid)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (action) {
|
||||||
|
layoutManagerActionStore.removeAction(actionTriggerUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.coWebsitesActionTriggerByPlace.delete(place);
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleFocusablePropertiesOnLeave(place: ITiledPlace): void {
|
||||||
|
if (!place.properties) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const focusable = place.properties.find((property) => property.name === GameMapProperties.FOCUSABLE);
|
||||||
|
if (focusable && focusable.value === true) {
|
||||||
|
this.scene.getCameraManager().leaveFocusMode(this.scene.CurrentPlayer, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ import { followUsersColorStore } from "../../Stores/FollowStore";
|
|||||||
import { GameSceneUserInputHandler } from "../UserInput/GameSceneUserInputHandler";
|
import { GameSceneUserInputHandler } from "../UserInput/GameSceneUserInputHandler";
|
||||||
import { locale } from "../../i18n/i18n-svelte";
|
import { locale } from "../../i18n/i18n-svelte";
|
||||||
import { i18nJson } from "../../i18n/locales";
|
import { i18nJson } from "../../i18n/locales";
|
||||||
import { localVolumeStore } from "../../Stores/MediaStore";
|
import { availabilityStatusStore, localVolumeStore } from "../../Stores/MediaStore";
|
||||||
import { StringUtils } from "../../Utils/StringUtils";
|
import { StringUtils } from "../../Utils/StringUtils";
|
||||||
import { startLayerNamesStore } from "../../Stores/StartLayerNamesStore";
|
import { startLayerNamesStore } from "../../Stores/StartLayerNamesStore";
|
||||||
import { JitsiCoWebsite } from "../../WebRtc/CoWebsite/JitsiCoWebsite";
|
import { JitsiCoWebsite } from "../../WebRtc/CoWebsite/JitsiCoWebsite";
|
||||||
@ -102,7 +102,6 @@ import CancelablePromise from "cancelable-promise";
|
|||||||
import { Deferred } from "ts-deferred";
|
import { Deferred } from "ts-deferred";
|
||||||
import { SuperLoaderPlugin } from "../Services/SuperLoaderPlugin";
|
import { SuperLoaderPlugin } from "../Services/SuperLoaderPlugin";
|
||||||
import { PlayerDetailsUpdatedMessage } from "../../Messages/ts-proto-generated/protos/messages";
|
import { PlayerDetailsUpdatedMessage } from "../../Messages/ts-proto-generated/protos/messages";
|
||||||
import { privacyShutdownStore } from "../../Stores/PrivacyShutdownStore";
|
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
initPosition: PointInterface | null;
|
initPosition: PointInterface | null;
|
||||||
reconnecting: boolean;
|
reconnecting: boolean;
|
||||||
@ -186,7 +185,6 @@ export class GameScene extends DirtyScene {
|
|||||||
private biggestAvailableAreaStoreUnsubscribe!: () => void;
|
private biggestAvailableAreaStoreUnsubscribe!: () => void;
|
||||||
MapUrlFile: string;
|
MapUrlFile: string;
|
||||||
roomUrl: string;
|
roomUrl: string;
|
||||||
instance: string;
|
|
||||||
|
|
||||||
currentTick!: number;
|
currentTick!: number;
|
||||||
lastSentTick!: number; // The last tick at which a position was sent.
|
lastSentTick!: number; // The last tick at which a position was sent.
|
||||||
@ -235,7 +233,6 @@ export class GameScene extends DirtyScene {
|
|||||||
});
|
});
|
||||||
this.Terrains = [];
|
this.Terrains = [];
|
||||||
this.groups = new Map<number, Sprite>();
|
this.groups = new Map<number, Sprite>();
|
||||||
this.instance = room.getInstance();
|
|
||||||
|
|
||||||
this.MapUrlFile = MapUrlFile;
|
this.MapUrlFile = MapUrlFile;
|
||||||
this.roomUrl = room.key;
|
this.roomUrl = room.key;
|
||||||
@ -252,6 +249,8 @@ export class GameScene extends DirtyScene {
|
|||||||
this.listenToIframeEvents();
|
this.listenToIframeEvents();
|
||||||
|
|
||||||
this.load.image("iconTalk", "/resources/icons/icon_talking.png");
|
this.load.image("iconTalk", "/resources/icons/icon_talking.png");
|
||||||
|
this.load.image("iconStatusIndicatorInside", "/resources/icons/icon_status_indicator_inside.png");
|
||||||
|
this.load.image("iconStatusIndicatorOutline", "/resources/icons/icon_status_indicator_outline.png");
|
||||||
|
|
||||||
if (touchScreenManager.supportTouchScreen) {
|
if (touchScreenManager.supportTouchScreen) {
|
||||||
this.load.image(joystickBaseKey, joystickBaseImg);
|
this.load.image(joystickBaseKey, joystickBaseImg);
|
||||||
@ -697,6 +696,11 @@ export class GameScene extends DirtyScene {
|
|||||||
this.tryChangeShowVoiceIndicatorState(this.jitsiDominantSpeaker && this.jitsiParticipantsCount > 1);
|
this.tryChangeShowVoiceIndicatorState(this.jitsiDominantSpeaker && this.jitsiParticipantsCount > 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
availabilityStatusStore.subscribe((status) => {
|
||||||
|
this.connection?.emitPlayerStatusChange(status);
|
||||||
|
this.CurrentPlayer.setStatus(status);
|
||||||
|
});
|
||||||
|
|
||||||
this.emoteUnsubscribe = emoteStore.subscribe((emote) => {
|
this.emoteUnsubscribe = emoteStore.subscribe((emote) => {
|
||||||
if (emote) {
|
if (emote) {
|
||||||
this.CurrentPlayer?.playEmote(emote.unicode);
|
this.CurrentPlayer?.playEmote(emote.unicode);
|
||||||
@ -723,10 +727,6 @@ export class GameScene extends DirtyScene {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.privacyShutdownStoreUnsubscribe = privacyShutdownStore.subscribe((away) => {
|
|
||||||
this.connection?.emitPlayerAway(away);
|
|
||||||
});
|
|
||||||
|
|
||||||
Promise.all([
|
Promise.all([
|
||||||
this.connectionAnswerPromiseDeferred.promise as Promise<unknown>,
|
this.connectionAnswerPromiseDeferred.promise as Promise<unknown>,
|
||||||
...scriptPromises,
|
...scriptPromises,
|
||||||
@ -785,7 +785,7 @@ export class GameScene extends DirtyScene {
|
|||||||
characterLayers: message.characterLayers,
|
characterLayers: message.characterLayers,
|
||||||
name: message.name,
|
name: message.name,
|
||||||
position: message.position,
|
position: message.position,
|
||||||
away: message.away,
|
status: message.status,
|
||||||
visitCardUrl: message.visitCardUrl,
|
visitCardUrl: message.visitCardUrl,
|
||||||
companion: message.companion,
|
companion: message.companion,
|
||||||
userUuid: message.userUuid,
|
userUuid: message.userUuid,
|
||||||
@ -925,38 +925,15 @@ export class GameScene extends DirtyScene {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.gameMap.onEnterZone((zones) => {
|
this.gameMap.onEnterArea((areas) => {
|
||||||
for (const zone of zones) {
|
areas.forEach((area) => {
|
||||||
const focusable = zone.properties?.find((property) => property.name === "focusable");
|
iframeListener.sendEnterAreaEvent(area.name);
|
||||||
if (focusable && focusable.value === true) {
|
|
||||||
const zoomMargin = zone.properties?.find((property) => property.name === "zoom_margin");
|
|
||||||
this.cameraManager.enterFocusMode(
|
|
||||||
{
|
|
||||||
x: zone.x + zone.width * 0.5,
|
|
||||||
y: zone.y + zone.height * 0.5,
|
|
||||||
width: zone.width,
|
|
||||||
height: zone.height,
|
|
||||||
},
|
|
||||||
zoomMargin ? Math.max(0, Number(zoomMargin.value)) : undefined
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zones.forEach((zone) => {
|
|
||||||
iframeListener.sendEnterZoneEvent(zone.name);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.gameMap.onLeaveZone((zones) => {
|
this.gameMap.onLeaveArea((areas) => {
|
||||||
for (const zone of zones) {
|
areas.forEach((area) => {
|
||||||
const focusable = zone.properties?.find((property) => property.name === "focusable");
|
iframeListener.sendLeaveAreaEvent(area.name);
|
||||||
if (focusable && focusable.value === true) {
|
|
||||||
this.cameraManager.leaveFocusMode(this.CurrentPlayer, 1000);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zones.forEach((zone) => {
|
|
||||||
iframeListener.sendLeaveZoneEvent(zone.name);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1993,8 +1970,8 @@ export class GameScene extends DirtyScene {
|
|||||||
if (addPlayerData.outlineColor !== undefined) {
|
if (addPlayerData.outlineColor !== undefined) {
|
||||||
player.setApiOutlineColor(addPlayerData.outlineColor);
|
player.setApiOutlineColor(addPlayerData.outlineColor);
|
||||||
}
|
}
|
||||||
if (addPlayerData.away !== undefined) {
|
if (addPlayerData.status !== undefined) {
|
||||||
player.setAwayStatus(addPlayerData.away, true);
|
player.setStatus(addPlayerData.status, true);
|
||||||
}
|
}
|
||||||
this.MapPlayers.add(player);
|
this.MapPlayers.add(player);
|
||||||
this.MapPlayersByKey.set(player.userId, player);
|
this.MapPlayersByKey.set(player.userId, player);
|
||||||
@ -2145,8 +2122,8 @@ export class GameScene extends DirtyScene {
|
|||||||
if (message.details?.showVoiceIndicator !== undefined) {
|
if (message.details?.showVoiceIndicator !== undefined) {
|
||||||
character.showTalkIcon(message.details?.showVoiceIndicator);
|
character.showTalkIcon(message.details?.showVoiceIndicator);
|
||||||
}
|
}
|
||||||
if (message.details?.away !== undefined) {
|
if (message.details?.status !== undefined) {
|
||||||
character.setAwayStatus(message.details?.away);
|
character.setStatus(message.details?.status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2190,13 +2167,10 @@ export class GameScene extends DirtyScene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enableMediaBehaviors() {
|
public enableMediaBehaviors() {
|
||||||
const silent = this.gameMap.getCurrentProperties().get(GameMapProperties.SILENT);
|
|
||||||
this.connection?.setSilent(!!silent);
|
|
||||||
mediaManager.showMyCamera();
|
mediaManager.showMyCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
public disableMediaBehaviors() {
|
public disableMediaBehaviors() {
|
||||||
this.connection?.setSilent(true);
|
|
||||||
mediaManager.hideMyCamera();
|
mediaManager.hideMyCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { AvailabilityStatus } from "../../Messages/ts-proto-generated/protos/messages";
|
||||||
import type { BodyResourceDescriptionInterface } from "../Entity/PlayerTextures";
|
import type { BodyResourceDescriptionInterface } from "../Entity/PlayerTextures";
|
||||||
|
|
||||||
export interface PlayerInterface {
|
export interface PlayerInterface {
|
||||||
@ -7,7 +8,7 @@ export interface PlayerInterface {
|
|||||||
visitCardUrl: string | null;
|
visitCardUrl: string | null;
|
||||||
companion: string | null;
|
companion: string | null;
|
||||||
userUuid: string;
|
userUuid: string;
|
||||||
away: boolean;
|
status: AvailabilityStatus;
|
||||||
color?: string;
|
color?: string;
|
||||||
outlineColor?: number;
|
outlineColor?: number;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ export class PlayerMovement {
|
|||||||
const y =
|
const y =
|
||||||
(this.endPosition.y - this.startPosition.y) * ((tick - this.startTick) / (this.endTick - this.startTick)) +
|
(this.endPosition.y - this.startPosition.y) * ((tick - this.startTick) / (this.endTick - this.startTick)) +
|
||||||
this.startPosition.y;
|
this.startPosition.y;
|
||||||
//console.log('Computed position ', x, y)
|
|
||||||
return {
|
return {
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
|
@ -67,4 +67,20 @@ export class TexturesHelper {
|
|||||||
rectangleTexture.generateTexture(textureKey, width, height);
|
rectangleTexture.generateTexture(textureKey, width, height);
|
||||||
rectangleTexture.destroy();
|
rectangleTexture.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static createCircleTexture(
|
||||||
|
scene: Phaser.Scene,
|
||||||
|
textureKey: string,
|
||||||
|
radius: number,
|
||||||
|
color: number,
|
||||||
|
outlineColor?: number,
|
||||||
|
outlineThickness?: number
|
||||||
|
): void {
|
||||||
|
const circleTexture = scene.add.graphics().fillStyle(color, 1).fillCircle(radius, radius, radius);
|
||||||
|
if (outlineColor) {
|
||||||
|
circleTexture.lineStyle(outlineThickness ?? 1, outlineColor).strokeCircle(radius, radius, radius);
|
||||||
|
}
|
||||||
|
circleTexture.generateTexture(textureKey, radius * 2, radius * 2);
|
||||||
|
circleTexture.destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ export class Player extends Character {
|
|||||||
companionTexturePromise?: CancelablePromise<string>
|
companionTexturePromise?: CancelablePromise<string>
|
||||||
) {
|
) {
|
||||||
super(Scene, x, y, texturesPromise, name, direction, moving, 1, true, companion, companionTexturePromise);
|
super(Scene, x, y, texturesPromise, name, direction, moving, 1, true, companion, companionTexturePromise);
|
||||||
this.statusDot.setVisible(false);
|
|
||||||
//the current player model should be push away by other players to prevent conflict
|
//the current player model should be push away by other players to prevent conflict
|
||||||
this.getBody().setImmovable(false);
|
this.getBody().setImmovable(false);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import { peerStore } from "./PeerStore";
|
|||||||
import { privacyShutdownStore } from "./PrivacyShutdownStore";
|
import { privacyShutdownStore } from "./PrivacyShutdownStore";
|
||||||
import { MediaStreamConstraintsError } from "./Errors/MediaStreamConstraintsError";
|
import { MediaStreamConstraintsError } from "./Errors/MediaStreamConstraintsError";
|
||||||
import { SoundMeter } from "../Phaser/Components/SoundMeter";
|
import { SoundMeter } from "../Phaser/Components/SoundMeter";
|
||||||
|
import { AvailabilityStatus } from "../Messages/ts-proto-generated/protos/messages";
|
||||||
import deepEqual from "fast-deep-equal";
|
import deepEqual from "fast-deep-equal";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -179,10 +180,19 @@ function createVideoConstraintStore() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export const inJitsiStore = writable(false);
|
||||||
* A store containing if user is silent, so if he is in silent zone. This permit to show et hide camera of user
|
export const silentStore = writable(false);
|
||||||
*/
|
|
||||||
export const isSilentStore = writable(false);
|
export const availabilityStatusStore = derived(
|
||||||
|
[inJitsiStore, silentStore, privacyShutdownStore],
|
||||||
|
([$inJitsiStore, $silentStore, $privacyShutdownStore]) => {
|
||||||
|
if ($inJitsiStore) return AvailabilityStatus.JITSI;
|
||||||
|
if ($silentStore) return AvailabilityStatus.SILENT;
|
||||||
|
if ($privacyShutdownStore) return AvailabilityStatus.AWAY;
|
||||||
|
return AvailabilityStatus.ONLINE;
|
||||||
|
},
|
||||||
|
AvailabilityStatus.ONLINE
|
||||||
|
);
|
||||||
|
|
||||||
export const videoConstraintStore = createVideoConstraintStore();
|
export const videoConstraintStore = createVideoConstraintStore();
|
||||||
|
|
||||||
@ -241,7 +251,7 @@ export const mediaStreamConstraintsStore = derived(
|
|||||||
audioConstraintStore,
|
audioConstraintStore,
|
||||||
privacyShutdownStore,
|
privacyShutdownStore,
|
||||||
cameraEnergySavingStore,
|
cameraEnergySavingStore,
|
||||||
isSilentStore,
|
availabilityStatusStore,
|
||||||
],
|
],
|
||||||
(
|
(
|
||||||
[
|
[
|
||||||
@ -253,7 +263,7 @@ export const mediaStreamConstraintsStore = derived(
|
|||||||
$audioConstraintStore,
|
$audioConstraintStore,
|
||||||
$privacyShutdownStore,
|
$privacyShutdownStore,
|
||||||
$cameraEnergySavingStore,
|
$cameraEnergySavingStore,
|
||||||
$isSilentStore,
|
$availabilityStatusStore,
|
||||||
],
|
],
|
||||||
set
|
set
|
||||||
) => {
|
) => {
|
||||||
@ -310,7 +320,7 @@ export const mediaStreamConstraintsStore = derived(
|
|||||||
//currentAudioConstraint = false;
|
//currentAudioConstraint = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($isSilentStore === true) {
|
if ($availabilityStatusStore === AvailabilityStatus.SILENT) {
|
||||||
currentVideoConstraint = false;
|
currentVideoConstraint = false;
|
||||||
currentAudioConstraint = false;
|
currentAudioConstraint = false;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,27 @@
|
|||||||
import { get, writable } from "svelte/store";
|
import { get, writable } from "svelte/store";
|
||||||
import Timeout = NodeJS.Timeout;
|
import Timeout = NodeJS.Timeout;
|
||||||
import { userIsAdminStore } from "./GameStore";
|
import { userIsAdminStore } from "./GameStore";
|
||||||
import { CONTACT_URL } from "../Enum/EnvironmentVariable";
|
import { CONTACT_URL, IDENTITY_URL, PROFILE_URL } from "../Enum/EnvironmentVariable";
|
||||||
import { analyticsClient } from "../Administration/AnalyticsClient";
|
import { analyticsClient } from "../Administration/AnalyticsClient";
|
||||||
import type { Translation } from "../i18n/i18n-types";
|
import type { Translation } from "../i18n/i18n-types";
|
||||||
|
import axios from "axios";
|
||||||
|
import { localUserStore } from "../Connexion/LocalUserStore";
|
||||||
|
|
||||||
export const menuIconVisiblilityStore = writable(false);
|
export const menuIconVisiblilityStore = writable(false);
|
||||||
export const menuVisiblilityStore = writable(false);
|
export const menuVisiblilityStore = writable(false);
|
||||||
menuVisiblilityStore.subscribe((value) => {
|
|
||||||
if (value) analyticsClient.openedMenu();
|
|
||||||
});
|
|
||||||
export const menuInputFocusStore = writable(false);
|
export const menuInputFocusStore = writable(false);
|
||||||
export const userIsConnected = writable(false);
|
export const userIsConnected = writable(false);
|
||||||
|
export const profileAvailable = writable(true);
|
||||||
|
|
||||||
|
menuVisiblilityStore.subscribe((value) => {
|
||||||
|
if (value) analyticsClient.openedMenu();
|
||||||
|
if (userIsConnected && value && IDENTITY_URL != null) {
|
||||||
|
axios.get(getMeUrl()).catch((err) => {
|
||||||
|
console.error("menuVisiblilityStore => err => ", err);
|
||||||
|
profileAvailable.set(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let warningContainerTimeout: Timeout | null = null;
|
let warningContainerTimeout: Timeout | null = null;
|
||||||
function createWarningContainerStore() {
|
function createWarningContainerStore() {
|
||||||
@ -179,3 +189,11 @@ export function handleMenuUnregisterEvent(menuName: string) {
|
|||||||
subMenusStore.removeScriptingMenu(menuName);
|
subMenusStore.removeScriptingMenu(menuName);
|
||||||
customMenuIframe.delete(menuName);
|
customMenuIframe.delete(menuName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getProfileUrl() {
|
||||||
|
return PROFILE_URL + `?token=${localUserStore.getAuthToken()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMeUrl() {
|
||||||
|
return IDENTITY_URL + `?token=${localUserStore.getAuthToken()}`;
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ import { writable } from "svelte/store";
|
|||||||
import type { PlayerInterface } from "../Phaser/Game/PlayerInterface";
|
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 { AvailabilityStatus } from "../Messages/ts-proto-generated/protos/messages";
|
||||||
|
|
||||||
let idCount = 0;
|
let idCount = 0;
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ function createPlayersStore() {
|
|||||||
visitCardUrl: message.visitCardUrl,
|
visitCardUrl: message.visitCardUrl,
|
||||||
companion: message.companion,
|
companion: message.companion,
|
||||||
userUuid: message.userUuid,
|
userUuid: message.userUuid,
|
||||||
away: message.away,
|
status: message.status,
|
||||||
color: getRandomColor(),
|
color: getRandomColor(),
|
||||||
});
|
});
|
||||||
return users;
|
return users;
|
||||||
@ -58,7 +59,7 @@ function createPlayersStore() {
|
|||||||
characterLayers: [],
|
characterLayers: [],
|
||||||
visitCardUrl: null,
|
visitCardUrl: null,
|
||||||
companion: null,
|
companion: null,
|
||||||
away: false,
|
status: AvailabilityStatus.ONLINE,
|
||||||
userUuid: "dummy",
|
userUuid: "dummy",
|
||||||
color: getRandomColor(),
|
color: getRandomColor(),
|
||||||
});
|
});
|
||||||
|
@ -9,4 +9,21 @@ export class StringUtils {
|
|||||||
}
|
}
|
||||||
return { x: values[0], y: values[1] };
|
return { x: values[0], y: values[1] };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes a "short URL" hash of the string passed in parameter.
|
||||||
|
*/
|
||||||
|
public static shortHash = function (s: string): string {
|
||||||
|
let hash = 0;
|
||||||
|
const strLength = s.length;
|
||||||
|
if (strLength === 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
for (let i = 0; i < strLength; i++) {
|
||||||
|
const c = s.charCodeAt(i);
|
||||||
|
hash = (hash << 5) - hash + c;
|
||||||
|
hash = hash & hash; // Convert to 32bit integer
|
||||||
|
}
|
||||||
|
return Math.abs(hash).toString(36);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import { get } from "svelte/store";
|
|||||||
import CancelablePromise from "cancelable-promise";
|
import CancelablePromise from "cancelable-promise";
|
||||||
import { gameManager } from "../Phaser/Game/GameManager";
|
import { gameManager } from "../Phaser/Game/GameManager";
|
||||||
import { jitsiParticipantsCountStore, userIsJitsiDominantSpeakerStore } from "../Stores/GameStore";
|
import { jitsiParticipantsCountStore, userIsJitsiDominantSpeakerStore } from "../Stores/GameStore";
|
||||||
|
import { StringUtils } from "../Utils/StringUtils";
|
||||||
|
|
||||||
interface jitsiConfigInterface {
|
interface jitsiConfigInterface {
|
||||||
startWithAudioMuted: boolean;
|
startWithAudioMuted: boolean;
|
||||||
@ -120,7 +121,7 @@ const slugify = (...args: (string | number)[]): string => {
|
|||||||
.replace(/[\u0300-\u036f]/g, "") // remove all previously split accents
|
.replace(/[\u0300-\u036f]/g, "") // remove all previously split accents
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.trim()
|
.trim()
|
||||||
.replace(/[^a-z0-9 ]/g, "") // remove all chars not letters, numbers and spaces (to be replaced)
|
.replace(/[^a-zA-Z0-9]/g, "") // remove all chars not letters, numbers (to be replaced)
|
||||||
.replace(/\s+/g, "-"); // separator
|
.replace(/\s+/g, "-"); // separator
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -135,11 +136,8 @@ class JitsiFactory {
|
|||||||
/**
|
/**
|
||||||
* Slugifies the room name and prepends the room name with the instance
|
* Slugifies the room name and prepends the room name with the instance
|
||||||
*/
|
*/
|
||||||
public getRoomName(roomName: string, instance: string): string {
|
public getRoomName(roomName: string, roomId: string, addPrefix: boolean): string {
|
||||||
if (!instance || instance == "") {
|
return slugify((addPrefix ? StringUtils.shortHash(roomId) + "-" : "") + roomName);
|
||||||
return slugify(roomName);
|
|
||||||
}
|
|
||||||
return slugify(instance.replace("/", "-") + "-" + roomName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public start(
|
public start(
|
||||||
|
@ -58,11 +58,11 @@ const menu: NonNullable<Translation["menu"]> = {
|
|||||||
title: "Sprache",
|
title: "Sprache",
|
||||||
},
|
},
|
||||||
privacySettings: {
|
privacySettings: {
|
||||||
title: "Einstellungen Abwesenheitsmodus",
|
title: "Away mode", //TODO: translate
|
||||||
explanation:
|
explanation:
|
||||||
"Falls der WorkAdventure Tab nicht aktiv ist wird in den Abwesenheitsmodus umgeschaltet. Für diesen Modus kann eingestellt werden, ob die Kamera und/oder das Mikrofon deaktiviert sind solange der Tab nicht sichtbar ist.",
|
'While the WorkAdventure tab in your browser is not visible. WorkAdventure switches in "away mode.', //TODO: translate
|
||||||
cameraToggle: "Kamera",
|
cameraToggle: "Keep camera active in away mode", //TODO: translate
|
||||||
microphoneToggle: "Mikrofon",
|
microphoneToggle: "Keep camera active in away mode", //TODO: translate
|
||||||
},
|
},
|
||||||
save: {
|
save: {
|
||||||
warning: "(Das Spiel wird nach dem Speichern neugestartet)",
|
warning: "(Das Spiel wird nach dem Speichern neugestartet)",
|
||||||
|
@ -3,17 +3,18 @@ import type { Translation } from "../i18n-types";
|
|||||||
const report: NonNullable<Translation["report"]> = {
|
const report: NonNullable<Translation["report"]> = {
|
||||||
block: {
|
block: {
|
||||||
title: "Blockieren",
|
title: "Blockieren",
|
||||||
content: "Blockiere jede Kommunikation von und zu {userName}. Kann jederzeit rückgängig gemacht werden.",
|
content: "Blockiere jegliche Kommunikation mit {userName}. Kann jederzeit rückgängig gemacht werden.",
|
||||||
unblock: "Blockierung für diesen User aufheben",
|
unblock: "Blockierung für diesen Nutzer aufheben",
|
||||||
block: "Blockiere diese User",
|
block: "Blockiere diesen Nutzer",
|
||||||
},
|
},
|
||||||
title: "Melden",
|
title: "Melden",
|
||||||
content: "Verfasse eine Meldung an die Administratoren dieses Raums. Diese können den User anschließend bannen.",
|
content:
|
||||||
|
"Verfasse eine Beschwerde an die Administratoren dieses Raums. Diese können den Nutzer anschließend bannen.",
|
||||||
message: {
|
message: {
|
||||||
title: "Deine Nachricht: ",
|
title: "Deine Nachricht: ",
|
||||||
empty: "Bitte einen Text angeben.",
|
empty: "Bitte Text eingeben.",
|
||||||
},
|
},
|
||||||
submit: "Diesen User melden",
|
submit: "Diesen Nutzer melden",
|
||||||
moderate: {
|
moderate: {
|
||||||
title: "{userName} moderieren",
|
title: "{userName} moderieren",
|
||||||
block: "Blockieren",
|
block: "Blockieren",
|
||||||
|
@ -58,11 +58,11 @@ const menu: BaseTranslation = {
|
|||||||
title: "Language",
|
title: "Language",
|
||||||
},
|
},
|
||||||
privacySettings: {
|
privacySettings: {
|
||||||
title: "Away mode settings",
|
title: "Away mode",
|
||||||
explanation:
|
explanation:
|
||||||
'When the WorkAdventure tab is not visible, it switches to "away mode". In this mode, you can decide to automatically disable your webcam and/or microphone for as long as the tab stays hidden.',
|
'While the WorkAdventure tab in your browser is not visible. WorkAdventure switches to "away mode"',
|
||||||
cameraToggle: "Camera",
|
cameraToggle: 'Keep camera active in "away mode"',
|
||||||
microphoneToggle: "Microphone",
|
microphoneToggle: 'Keep microphone active in "away mode"',
|
||||||
},
|
},
|
||||||
save: {
|
save: {
|
||||||
warning: "(Saving these settings will restart the game)",
|
warning: "(Saving these settings will restart the game)",
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
//TextGlobalMessage
|
|
||||||
|
|
||||||
// TODO: load on demand with TextGlobalMessage component
|
|
||||||
@import "quill/dist/quill.snow.css";
|
|
||||||
|
|
||||||
section.section-input-send-text {
|
|
||||||
--height-toolbar: 20%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
.ql-toolbar{
|
|
||||||
max-height: var(--height-toolbar);
|
|
||||||
background: whitesmoke;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.input-send-text{
|
|
||||||
height: calc(100% - var(--height-toolbar));
|
|
||||||
overflow: auto;
|
|
||||||
|
|
||||||
color: whitesmoke;
|
|
||||||
font-size: 1rem;
|
|
||||||
|
|
||||||
.ql-editor.ql-blank::before {
|
|
||||||
color: whitesmoke;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-tooltip {
|
|
||||||
top: 40% !important;
|
|
||||||
left: 20% !important;
|
|
||||||
|
|
||||||
color: whitesmoke;
|
|
||||||
background-color: #333333;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include media-breakpoint-up(md) {
|
|
||||||
section.section-input-send-text {
|
|
||||||
--height-toolbar: 30%;
|
|
||||||
|
|
||||||
.ql-toolbar {
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
@include media-breakpoint-up(md) {
|
@media screen and (orientation:portrait) {
|
||||||
#main-container {
|
#main-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@include media-breakpoint-down(lg) {
|
@media screen and (orientation:landscape) {
|
||||||
#cowebsite {
|
#cowebsite {
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -5,4 +5,3 @@
|
|||||||
@import "cowebsite.scss";
|
@import "cowebsite.scss";
|
||||||
@import "fonts.scss";
|
@import "fonts.scss";
|
||||||
@import "style";
|
@import "style";
|
||||||
@import "TextGlobalMessageSvelte-Style";
|
|
||||||
|
@ -28,6 +28,7 @@ export default defineConfig({
|
|||||||
"ADMIN_URL",
|
"ADMIN_URL",
|
||||||
"CONTACT_URL",
|
"CONTACT_URL",
|
||||||
"PROFILE_URL",
|
"PROFILE_URL",
|
||||||
|
"IDENTITY_URL",
|
||||||
"ICON_URL",
|
"ICON_URL",
|
||||||
"DEBUG_MODE",
|
"DEBUG_MODE",
|
||||||
"STUN_SERVER",
|
"STUN_SERVER",
|
||||||
|
@ -50,10 +50,10 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<input type="radio" name="test-door-map"> Success <input type="radio" name="test-door-map"> Failure <input type="radio" name="test-door-map" checked> Pending
|
<input type="radio" name="test-pathfinding"> Success <input type="radio" name="test-pathfinding"> Failure <input type="radio" name="test-pathfinding" checked> Pending
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="#" class="testLink" data-testmap="DoorTest/map.json" target="_blank">Test Doors</a>
|
<a href="#" class="testLink" data-testmap="Pathfinding/map.json" target="_blank">Test Pathfinding</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -168,6 +168,14 @@
|
|||||||
<a href="#" class="testLink" data-testmap="layer-visibility.json" target="_blank">Layer visibility + Layer size and offset</a>
|
<a href="#" class="testLink" data-testmap="layer-visibility.json" target="_blank">Layer visibility + Layer size and offset</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="radio" name="test-tiled-objects"> Success <input type="radio" name="test-tiled-objects"> Failure <input type="radio" name="test-tiled-objects" checked> Pending
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="#" class="testLink" data-testmap="tiled_objects.json" target="_blank">Test Tiled Objects with properties</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<h2>Iframe API</h2>
|
<h2>Iframe API</h2>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
@ -471,6 +479,14 @@
|
|||||||
<a href="#" class="testLink" data-testmap="AwayModeSettings/away_mode_settings.json" target="_blank">Away mode settings</a>
|
<a href="#" class="testLink" data-testmap="AwayModeSettings/away_mode_settings.json" target="_blank">Away mode settings</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="radio" name="test-status-indicator"> Success <input type="radio" name="test-status-indicator"> Failure <input type="radio" name="test-status-indicator" checked> Pending
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="#" class="testLink" data-testmap="status_indicator.json" target="_blank">Test Status Indicator</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
|
@ -43,6 +43,11 @@
|
|||||||
"type":"string",
|
"type":"string",
|
||||||
"value":"{\"DEFAULT_BACKGROUND\":\"#77ee77\"}"
|
"value":"{\"DEFAULT_BACKGROUND\":\"#77ee77\"}"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"jitsiNoPrefix",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"jitsiRoom",
|
"name":"jitsiRoom",
|
||||||
"type":"string",
|
"type":"string",
|
||||||
@ -65,7 +70,7 @@
|
|||||||
"name":"floorLayer",
|
"name":"floorLayer",
|
||||||
"objects":[
|
"objects":[
|
||||||
{
|
{
|
||||||
"height":83.6666666666666,
|
"height":110.891622876526,
|
||||||
"id":1,
|
"id":1,
|
||||||
"name":"",
|
"name":"",
|
||||||
"rotation":0,
|
"rotation":0,
|
||||||
@ -73,14 +78,14 @@
|
|||||||
{
|
{
|
||||||
"fontfamily":"Sans Serif",
|
"fontfamily":"Sans Serif",
|
||||||
"pixelsize":13,
|
"pixelsize":13,
|
||||||
"text":"Test:\nWalk on the carpet and press space\nResult:\nJitsi opens, background in green and audio\/video is muted",
|
"text":"Test:\nWalk on the carpet and press space\nResult:\nJitsi opens, background in green and audio\/video is muted.\nThe name of the room (displayed at the top of Jitsi) is \"Myroom Avec Espace EA\"",
|
||||||
"wrap":true
|
"wrap":true
|
||||||
},
|
},
|
||||||
"type":"",
|
"type":"",
|
||||||
"visible":true,
|
"visible":true,
|
||||||
"width":315.4375,
|
"width":315.4375,
|
||||||
"x":2.28125,
|
"x":1.48051599382768,
|
||||||
"y":235.166666666667
|
"y":209.535838407429
|
||||||
}],
|
}],
|
||||||
"opacity":1,
|
"opacity":1,
|
||||||
"type":"objectgroup",
|
"type":"objectgroup",
|
||||||
|
363
maps/tests/status_indicator.json
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":17,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":17,
|
||||||
|
"id":40,
|
||||||
|
"name":"jitsiLayer",
|
||||||
|
"opacity":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"jitsiRoom",
|
||||||
|
"type":"string",
|
||||||
|
"value":"meeting"
|
||||||
|
}],
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":17,
|
||||||
|
"id":41,
|
||||||
|
"name":"jitsiChillzone",
|
||||||
|
"opacity":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"jitsiRoom",
|
||||||
|
"type":"string",
|
||||||
|
"value":"ChillZone"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"jitsiTrigger",
|
||||||
|
"type":"string",
|
||||||
|
"value":"onaction"
|
||||||
|
}],
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 445, 445, 445, 445, 445, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 445, 445, 445, 445, 445, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 445, 445, 445, 445, 445, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 445, 445, 445, 445, 445, 445, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":17,
|
||||||
|
"id":39,
|
||||||
|
"name":"silentZone",
|
||||||
|
"opacity":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"silent",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}],
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":17,
|
||||||
|
"id":6,
|
||||||
|
"name":"start",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 0, 0, 443, 443, 443, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 443, 443, 0, 0, 0, 0, 443, 443, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 443, 443, 0, 0, 0, 0, 443, 443, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 443, 443, 0, 0, 0, 0, 443, 443, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":17,
|
||||||
|
"id":7,
|
||||||
|
"name":"collisions",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201],
|
||||||
|
"height":17,
|
||||||
|
"id":4,
|
||||||
|
"name":"floor",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[49, 58, 58, 58, 58, 58, 58, 42, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 42, 57, 57, 57, 57, 57, 57, 57, 50, 45, 63, 63, 63, 63, 63, 63, 45, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 45, 63, 63, 63, 63, 63, 63, 63, 45, 45, 73, 73, 73, 73, 73, 73, 45, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 45, 73, 73, 73, 73, 73, 73, 73, 45, 45, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 45, 59, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 32, 58, 58, 58, 58, 58, 58, 58, 60, 83, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 84, 93, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 94],
|
||||||
|
"height":17,
|
||||||
|
"id":9,
|
||||||
|
"name":"walls",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 293, 0, 0, 0, 0, 293, 0, 107, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 107, 0, 0, 128, 1, 2, 3, 0, 0, 0, 0, 304, 296, 297, 296, 297, 304, 0, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 0, 0, 11, 12, 13, 0, 0, 0, 0, 315, 307, 308, 307, 308, 315, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 243, 0, 0, 0, 0, 2147483943, 0, 0, 0, 325, 340, 340, 326, 0, 0, 325, 340, 340, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 0, 283, 283, 0, 2147483954, 0, 0, 0, 0, 340, 340, 0, 0, 0, 0, 340, 340, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 294, 294, 0, 0, 0, 0, 0, 325, 340, 340, 326, 0, 0, 325, 340, 340, 326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 351, 351, 0, 0, 0, 0, 351, 351, 0, 0, 0, 0, 0, 0, 325, 273, 275, 326, 0, 0, 0, 394, 395, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 2147483923, 275, 326, 0, 0, 0, 405, 406, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 2147483923, 275, 326, 0, 0, 0, 416, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 325, 2147483923, 275, 326, 0, 0, 0, 427, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 284, 286, 0, 0, 0, 0, 438, 439, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483811, 2147483810, 2147483809, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":17,
|
||||||
|
"id":1,
|
||||||
|
"name":"furniture",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483909, 261, 0, 0, 0, 0, 2147483909, 261, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483909, 261, 0, 0, 0, 0, 2147483909, 261, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, 0, 0, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":17,
|
||||||
|
"id":33,
|
||||||
|
"name":"aboveFurniture",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":2,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[
|
||||||
|
{
|
||||||
|
"height":19,
|
||||||
|
"id":18,
|
||||||
|
"name":"",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"halign":"center",
|
||||||
|
"text":"SILENT",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":83,
|
||||||
|
"x":85.975051264525,
|
||||||
|
"y":146.001480975165
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height":78.6691729323309,
|
||||||
|
"id":19,
|
||||||
|
"name":"",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"text":"Get into silent zone to show red status dot for your WOKA",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":403.043745727956,
|
||||||
|
"x":131.178970152654,
|
||||||
|
"y":359.363978127136
|
||||||
|
}],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 329, 329, 0, 0, 0, 0, 329, 329, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 262, 263, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 428, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483801, 2147483800, 2147483799, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":17,
|
||||||
|
"id":3,
|
||||||
|
"name":"abovePlayer1",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":17,
|
||||||
|
"id":27,
|
||||||
|
"name":"abovePlayer2",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":17,
|
||||||
|
"id":28,
|
||||||
|
"name":"abovePlayer3",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":42,
|
||||||
|
"nextobjectid":20,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"mapCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"Credits: Valdo Romao https:\/\/www.linkedin.com\/in\/valdo-romao\/ \nLicense: CC-BY-SA 3.0 (http:\/\/creativecommons.org\/licenses\/by-sa\/3.0\/)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"mapDescription",
|
||||||
|
"type":"string",
|
||||||
|
"value":"A perfect virtual office to get started with WorkAdventure!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"mapImage",
|
||||||
|
"type":"string",
|
||||||
|
"value":"map.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"mapLink",
|
||||||
|
"type":"string",
|
||||||
|
"value":"https:\/\/thecodingmachine.github.io\/workadventure-map-starter-kit\/map.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"mapName",
|
||||||
|
"type":"string",
|
||||||
|
"value":"Starter kit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"script",
|
||||||
|
"type":"string",
|
||||||
|
"value":"..\/dist\/script.js"
|
||||||
|
}],
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.7.2",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":10,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"..\/assets\/tileset5_export.png",
|
||||||
|
"imageheight":320,
|
||||||
|
"imagewidth":320,
|
||||||
|
"margin":0,
|
||||||
|
"name":"tileset5_export",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"tilesetCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"\u00a9 2021 WorkAdventure <https:\/\/workadventu.re\/> \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)"
|
||||||
|
}],
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":100,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns":10,
|
||||||
|
"firstgid":101,
|
||||||
|
"image":"..\/assets\/tileset6_export.png",
|
||||||
|
"imageheight":320,
|
||||||
|
"imagewidth":320,
|
||||||
|
"margin":0,
|
||||||
|
"name":"tileset6_export",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"tilesetCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"\u00a9 2021 WorkAdventure <https:\/\/workadventu.re\/> \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)"
|
||||||
|
}],
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":100,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns":11,
|
||||||
|
"firstgid":201,
|
||||||
|
"image":"..\/assets\/tileset1.png",
|
||||||
|
"imageheight":352,
|
||||||
|
"imagewidth":352,
|
||||||
|
"margin":0,
|
||||||
|
"name":"tileset1",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"tilesetCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"\u00a9 2021 WorkAdventure <https:\/\/workadventu.re\/> \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)"
|
||||||
|
}],
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":121,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns":11,
|
||||||
|
"firstgid":322,
|
||||||
|
"image":"..\/assets\/tileset1-repositioning.png",
|
||||||
|
"imageheight":352,
|
||||||
|
"imagewidth":352,
|
||||||
|
"margin":0,
|
||||||
|
"name":"tileset1-repositioning",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"tilesetCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"\u00a9 2021 WorkAdventure <https:\/\/workadventu.re\/> \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)"
|
||||||
|
}],
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":121,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns":6,
|
||||||
|
"firstgid":443,
|
||||||
|
"image":"..\/assets\/Special_Zones.png",
|
||||||
|
"imageheight":64,
|
||||||
|
"imagewidth":192,
|
||||||
|
"margin":0,
|
||||||
|
"name":"Special_Zones",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"tilesetCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"\u00a9 2021 WorkAdventure <https:\/\/workadventu.re\/> \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)"
|
||||||
|
}],
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":12,
|
||||||
|
"tileheight":32,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":0,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":"1.6",
|
||||||
|
"width":31
|
||||||
|
}
|
427
maps/tests/tiled_objects.json
Normal file
@ -0,0 +1,427 @@
|
|||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":17,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 444, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":17,
|
||||||
|
"id":6,
|
||||||
|
"name":"start",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":17,
|
||||||
|
"id":7,
|
||||||
|
"name":"collisions",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 234, 234, 234, 234, 234, 234, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 201, 201, 201, 201, 201, 223, 223, 223, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 234, 234, 234, 234, 234, 234, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 223, 223, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 223, 223, 201, 234, 234, 234, 234, 234, 234, 234, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 223, 223, 201, 234, 234, 234, 234, 234, 234, 234, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 223, 223, 223, 223, 223, 223, 223, 223, 201, 234, 234, 234, 234, 234, 234, 234, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201],
|
||||||
|
"height":17,
|
||||||
|
"id":4,
|
||||||
|
"name":"floor",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[49, 58, 58, 58, 58, 58, 58, 42, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 42, 57, 57, 57, 57, 57, 57, 57, 50, 45, 63, 63, 63, 63, 63, 63, 45, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 45, 63, 63, 63, 63, 63, 63, 63, 45, 45, 73, 73, 73, 73, 73, 73, 45, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 45, 73, 73, 73, 73, 73, 73, 73, 45, 45, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 59, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 32, 58, 58, 58, 58, 58, 58, 58, 60, 83, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 84, 93, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 94],
|
||||||
|
"height":17,
|
||||||
|
"id":9,
|
||||||
|
"name":"walls",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":31,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":2,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[
|
||||||
|
{
|
||||||
|
"ellipse":true,
|
||||||
|
"height":128,
|
||||||
|
"id":9,
|
||||||
|
"name":"",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"jitsiRoom",
|
||||||
|
"type":"string",
|
||||||
|
"value":"Chill Room"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"jitsiTrigger",
|
||||||
|
"type":"string",
|
||||||
|
"value":"onaction"
|
||||||
|
}],
|
||||||
|
"rotation":0,
|
||||||
|
"type":"area",
|
||||||
|
"visible":true,
|
||||||
|
"width":320,
|
||||||
|
"x":317.331510594668,
|
||||||
|
"y":97.6404647983595
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height":130.187286397813,
|
||||||
|
"id":11,
|
||||||
|
"name":"",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"jitsiRoom",
|
||||||
|
"type":"string",
|
||||||
|
"value":"MeetingRoom"
|
||||||
|
}],
|
||||||
|
"rotation":0,
|
||||||
|
"type":"area",
|
||||||
|
"visible":true,
|
||||||
|
"width":192.568694463431,
|
||||||
|
"x":30.738664843928,
|
||||||
|
"y":94.0241512873092
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height":97.8323080428344,
|
||||||
|
"id":12,
|
||||||
|
"name":"silent zone area",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"silent",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}],
|
||||||
|
"rotation":0,
|
||||||
|
"type":"area",
|
||||||
|
"visible":true,
|
||||||
|
"width":225.115516062885,
|
||||||
|
"x":735.919799498747,
|
||||||
|
"y":352.398724082935
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height":62.2854864433812,
|
||||||
|
"id":13,
|
||||||
|
"name":"",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"focusable",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"openWebsite",
|
||||||
|
"type":"string",
|
||||||
|
"value":"https:\/\/www.youtube.com\/embed\/CvXUGIm_hkA?list=RDCvXUGIm_hkA"
|
||||||
|
}],
|
||||||
|
"rotation":0,
|
||||||
|
"type":"area",
|
||||||
|
"visible":true,
|
||||||
|
"width":96.736386420597,
|
||||||
|
"x":799.205285942128,
|
||||||
|
"y":96.736386420597
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height":127.762816131237,
|
||||||
|
"id":15,
|
||||||
|
"name":"",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"focusable",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"zoom_margin",
|
||||||
|
"type":"float",
|
||||||
|
"value":0.5
|
||||||
|
}],
|
||||||
|
"rotation":0,
|
||||||
|
"type":"area",
|
||||||
|
"visible":true,
|
||||||
|
"width":254.95010252905,
|
||||||
|
"x":448.422875370244,
|
||||||
|
"y":319.947824105719
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height":19,
|
||||||
|
"id":17,
|
||||||
|
"name":"",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"text":"FOCUSABLE ",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":93.848940533151,
|
||||||
|
"x":529.877534745956,
|
||||||
|
"y":358.459899749373
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height":19,
|
||||||
|
"id":18,
|
||||||
|
"name":"",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"text":"JITSI ON TRIGGER",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":164.367053998633,
|
||||||
|
"x":408.731032125769,
|
||||||
|
"y":150.521872863978
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height":19,
|
||||||
|
"id":19,
|
||||||
|
"name":"",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"text":"JITSI",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":43.2205513784461,
|
||||||
|
"x":100.440305308726,
|
||||||
|
"y":147.80963773069
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height":102.175210754158,
|
||||||
|
"id":20,
|
||||||
|
"name":"",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"halign":"center",
|
||||||
|
"text":"OPEN WEBSITE AND FOCUSABLE",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":99.2734107997265,
|
||||||
|
"x":796.580656185919,
|
||||||
|
"y":102.605718842561
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height":19,
|
||||||
|
"id":21,
|
||||||
|
"name":"",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"text":"SILENT ZONE",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":112.834586466165,
|
||||||
|
"x":799.292891319207,
|
||||||
|
"y":391.910799726589
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height":95.892082727209,
|
||||||
|
"id":22,
|
||||||
|
"name":"",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"focusable",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}],
|
||||||
|
"rotation":359.800363945476,
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":318.187448731897,
|
||||||
|
"x":32.4024392837801,
|
||||||
|
"y":352.890077348834
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"height":43.4101161995899,
|
||||||
|
"id":23,
|
||||||
|
"name":"",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"halign":"center",
|
||||||
|
"text":"THIS SHOULD NOT TRIGGER ANYTHING (TYPE IS NOT 'AREA')",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":288.225791752108,
|
||||||
|
"x":41.6752107541581,
|
||||||
|
"y":381.965937571201
|
||||||
|
}],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":40,
|
||||||
|
"nextobjectid":24,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"mapCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"Credits: Valdo Romao https:\/\/www.linkedin.com\/in\/valdo-romao\/ \nLicense: CC-BY-SA 3.0 (http:\/\/creativecommons.org\/licenses\/by-sa\/3.0\/)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"mapDescription",
|
||||||
|
"type":"string",
|
||||||
|
"value":"A perfect virtual office to get started with WorkAdventure!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"mapImage",
|
||||||
|
"type":"string",
|
||||||
|
"value":"map.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"mapLink",
|
||||||
|
"type":"string",
|
||||||
|
"value":"https:\/\/thecodingmachine.github.io\/workadventure-map-starter-kit\/map.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"mapName",
|
||||||
|
"type":"string",
|
||||||
|
"value":"Starter kit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"script",
|
||||||
|
"type":"string",
|
||||||
|
"value":"..\/dist\/script.js"
|
||||||
|
}],
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.7.2",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":10,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"..\/assets\/tileset5_export.png",
|
||||||
|
"imageheight":320,
|
||||||
|
"imagewidth":320,
|
||||||
|
"margin":0,
|
||||||
|
"name":"tileset5_export",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"tilesetCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"\u00a9 2021 WorkAdventure <https:\/\/workadventu.re\/> \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)"
|
||||||
|
}],
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":100,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns":10,
|
||||||
|
"firstgid":101,
|
||||||
|
"image":"..\/assets\/tileset6_export.png",
|
||||||
|
"imageheight":320,
|
||||||
|
"imagewidth":320,
|
||||||
|
"margin":0,
|
||||||
|
"name":"tileset6_export",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"tilesetCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"\u00a9 2021 WorkAdventure <https:\/\/workadventu.re\/> \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)"
|
||||||
|
}],
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":100,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns":11,
|
||||||
|
"firstgid":201,
|
||||||
|
"image":"..\/assets\/tileset1.png",
|
||||||
|
"imageheight":352,
|
||||||
|
"imagewidth":352,
|
||||||
|
"margin":0,
|
||||||
|
"name":"tileset1",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"tilesetCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"\u00a9 2021 WorkAdventure <https:\/\/workadventu.re\/> \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)"
|
||||||
|
}],
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":121,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns":11,
|
||||||
|
"firstgid":322,
|
||||||
|
"image":"..\/assets\/tileset1-repositioning.png",
|
||||||
|
"imageheight":352,
|
||||||
|
"imagewidth":352,
|
||||||
|
"margin":0,
|
||||||
|
"name":"tileset1-repositioning",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"tilesetCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"\u00a9 2021 WorkAdventure <https:\/\/workadventu.re\/> \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)"
|
||||||
|
}],
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":121,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns":6,
|
||||||
|
"firstgid":443,
|
||||||
|
"image":"..\/assets\/Special_Zones.png",
|
||||||
|
"imageheight":64,
|
||||||
|
"imagewidth":192,
|
||||||
|
"margin":0,
|
||||||
|
"name":"Special_Zones",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"tilesetCopyright",
|
||||||
|
"type":"string",
|
||||||
|
"value":"\u00a9 2021 WorkAdventure <https:\/\/workadventu.re\/> \nLicence: WORKADVENTURE SPECIFIC RESOURCES LICENSE (see LICENSE.assets file)"
|
||||||
|
}],
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":12,
|
||||||
|
"tileheight":32,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":0,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":"1.6",
|
||||||
|
"width":31
|
||||||
|
}
|
@ -4,6 +4,14 @@ import "google/protobuf/wrappers.proto";
|
|||||||
|
|
||||||
/*********** PARTIAL MESSAGES **************/
|
/*********** PARTIAL MESSAGES **************/
|
||||||
|
|
||||||
|
enum AvailabilityStatus {
|
||||||
|
UNCHANGED = 0;
|
||||||
|
ONLINE = 1;
|
||||||
|
SILENT = 2;
|
||||||
|
AWAY = 3;
|
||||||
|
JITSI = 4;
|
||||||
|
}
|
||||||
|
|
||||||
message PositionMessage {
|
message PositionMessage {
|
||||||
int32 x = 1;
|
int32 x = 1;
|
||||||
int32 y = 2;
|
int32 y = 2;
|
||||||
@ -29,10 +37,6 @@ message ViewportMessage {
|
|||||||
int32 bottom = 4;
|
int32 bottom = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SilentMessage {
|
|
||||||
bool silent = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message CharacterLayerMessage {
|
message CharacterLayerMessage {
|
||||||
string url = 1;
|
string url = 1;
|
||||||
string name = 2;
|
string name = 2;
|
||||||
@ -53,7 +57,7 @@ message SetPlayerDetailsMessage {
|
|||||||
google.protobuf.UInt32Value outlineColor = 3;
|
google.protobuf.UInt32Value outlineColor = 3;
|
||||||
google.protobuf.BoolValue removeOutlineColor = 4;
|
google.protobuf.BoolValue removeOutlineColor = 4;
|
||||||
google.protobuf.BoolValue showVoiceIndicator = 5;
|
google.protobuf.BoolValue showVoiceIndicator = 5;
|
||||||
google.protobuf.BoolValue away = 6;
|
AvailabilityStatus status = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UserMovesMessage {
|
message UserMovesMessage {
|
||||||
@ -106,7 +110,6 @@ message LockGroupPromptMessage {
|
|||||||
message ClientToServerMessage {
|
message ClientToServerMessage {
|
||||||
oneof message {
|
oneof message {
|
||||||
UserMovesMessage userMovesMessage = 2;
|
UserMovesMessage userMovesMessage = 2;
|
||||||
SilentMessage silentMessage = 3;
|
|
||||||
ViewportMessage viewportMessage = 4;
|
ViewportMessage viewportMessage = 4;
|
||||||
ItemEventMessage itemEventMessage = 5;
|
ItemEventMessage itemEventMessage = 5;
|
||||||
SetPlayerDetailsMessage setPlayerDetailsMessage = 6;
|
SetPlayerDetailsMessage setPlayerDetailsMessage = 6;
|
||||||
@ -207,7 +210,7 @@ message UserJoinedMessage {
|
|||||||
string userUuid = 7;
|
string userUuid = 7;
|
||||||
uint32 outlineColor = 8;
|
uint32 outlineColor = 8;
|
||||||
bool hasOutline = 9;
|
bool hasOutline = 9;
|
||||||
bool away = 10;
|
AvailabilityStatus status = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UserLeftMessage {
|
message UserLeftMessage {
|
||||||
@ -346,7 +349,7 @@ message JoinRoomMessage {
|
|||||||
CompanionMessage companion = 8;
|
CompanionMessage companion = 8;
|
||||||
string visitCardUrl = 9;
|
string visitCardUrl = 9;
|
||||||
string userRoomToken = 10;
|
string userRoomToken = 10;
|
||||||
bool away = 11;
|
AvailabilityStatus status = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UserJoinedZoneMessage {
|
message UserJoinedZoneMessage {
|
||||||
@ -360,7 +363,7 @@ message UserJoinedZoneMessage {
|
|||||||
string userUuid = 8;
|
string userUuid = 8;
|
||||||
uint32 outlineColor = 9;
|
uint32 outlineColor = 9;
|
||||||
bool hasOutline = 10;
|
bool hasOutline = 10;
|
||||||
bool away = 11;
|
AvailabilityStatus status = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UserLeftZoneMessage {
|
message UserLeftZoneMessage {
|
||||||
@ -405,7 +408,6 @@ message PusherToBackMessage {
|
|||||||
oneof message {
|
oneof message {
|
||||||
JoinRoomMessage joinRoomMessage = 1;
|
JoinRoomMessage joinRoomMessage = 1;
|
||||||
UserMovesMessage userMovesMessage = 2;
|
UserMovesMessage userMovesMessage = 2;
|
||||||
SilentMessage silentMessage = 3;
|
|
||||||
ItemEventMessage itemEventMessage = 4;
|
ItemEventMessage itemEventMessage = 4;
|
||||||
SetPlayerDetailsMessage setPlayerDetailsMessage = 5;
|
SetPlayerDetailsMessage setPlayerDetailsMessage = 5;
|
||||||
WebRtcSignalToServerMessage webRtcSignalToServerMessage = 6;
|
WebRtcSignalToServerMessage webRtcSignalToServerMessage = 6;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
import { BaseHttpController } from "./BaseHttpController";
|
import { BaseHttpController } from "./BaseHttpController";
|
||||||
import { adminApi } from "../Services/AdminApi";
|
import { adminApi, FetchMemberDataByUuidResponse } from "../Services/AdminApi";
|
||||||
import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager";
|
import { AuthTokenData, jwtTokenManager } from "../Services/JWTTokenManager";
|
||||||
import { parse } from "query-string";
|
import { parse } from "query-string";
|
||||||
import { openIDClient } from "../Services/OpenIDClient";
|
import { openIDClient } from "../Services/OpenIDClient";
|
||||||
@ -19,6 +19,7 @@ export class AuthenticateController extends BaseHttpController {
|
|||||||
this.register();
|
this.register();
|
||||||
this.anonymLogin();
|
this.anonymLogin();
|
||||||
this.profileCallback();
|
this.profileCallback();
|
||||||
|
this.me();
|
||||||
}
|
}
|
||||||
|
|
||||||
openIDLogin() {
|
openIDLogin() {
|
||||||
@ -180,7 +181,7 @@ export class AuthenticateController extends BaseHttpController {
|
|||||||
if (!code && !nonce) {
|
if (!code && !nonce) {
|
||||||
return res.json({ ...resUserData, authToken: token });
|
return res.json({ ...resUserData, authToken: token });
|
||||||
}
|
}
|
||||||
console.error("Token cannot to be check on OpenId provider");
|
console.error("Token cannot be checked on OpenId provider");
|
||||||
res.status(500);
|
res.status(500);
|
||||||
res.send("User cannot to be connected on openid provider");
|
res.send("User cannot to be connected on openid provider");
|
||||||
return;
|
return;
|
||||||
@ -255,7 +256,7 @@ export class AuthenticateController extends BaseHttpController {
|
|||||||
try {
|
try {
|
||||||
const authTokenData: AuthTokenData = jwtTokenManager.verifyJWTToken(token as string, false);
|
const authTokenData: AuthTokenData = jwtTokenManager.verifyJWTToken(token as string, false);
|
||||||
if (authTokenData.accessToken == undefined) {
|
if (authTokenData.accessToken == undefined) {
|
||||||
throw Error("Token cannot to be logout on Hydra");
|
throw Error("Token cannot be logout on Hydra");
|
||||||
}
|
}
|
||||||
await openIDClient.logoutUser(authTokenData.accessToken);
|
await openIDClient.logoutUser(authTokenData.accessToken);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -412,7 +413,7 @@ export class AuthenticateController extends BaseHttpController {
|
|||||||
try {
|
try {
|
||||||
const authTokenData: AuthTokenData = jwtTokenManager.verifyJWTToken(token as string, false);
|
const authTokenData: AuthTokenData = jwtTokenManager.verifyJWTToken(token as string, false);
|
||||||
if (authTokenData.accessToken == undefined) {
|
if (authTokenData.accessToken == undefined) {
|
||||||
throw Error("Token cannot to be check on Hydra");
|
throw Error("Token cannot be checked on OpenID connect provider");
|
||||||
}
|
}
|
||||||
await openIDClient.checkTokenAuth(authTokenData.accessToken);
|
await openIDClient.checkTokenAuth(authTokenData.accessToken);
|
||||||
|
|
||||||
@ -432,4 +433,80 @@ export class AuthenticateController extends BaseHttpController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @openapi
|
||||||
|
* /me:
|
||||||
|
* get:
|
||||||
|
* description: ???
|
||||||
|
* parameters:
|
||||||
|
* - name: "token"
|
||||||
|
* in: "query"
|
||||||
|
* description: "A JWT authentication token ???"
|
||||||
|
* required: true
|
||||||
|
* type: "string"
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Data of user connected
|
||||||
|
*/
|
||||||
|
me() {
|
||||||
|
// @ts-ignore
|
||||||
|
this.app.get("/me", async (req, res): void => {
|
||||||
|
const { token } = parse(req.path_query);
|
||||||
|
try {
|
||||||
|
//verify connected by token
|
||||||
|
if (token != undefined) {
|
||||||
|
try {
|
||||||
|
const authTokenData: AuthTokenData = jwtTokenManager.verifyJWTToken(token as string, false);
|
||||||
|
if (authTokenData.accessToken == undefined) {
|
||||||
|
throw Error("Token cannot to be checked on Hydra");
|
||||||
|
}
|
||||||
|
const me = await openIDClient.checkTokenAuth(authTokenData.accessToken);
|
||||||
|
|
||||||
|
//get login profile
|
||||||
|
res.status(200);
|
||||||
|
res.json({ ...me });
|
||||||
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
this.castErrorToResponse(error, res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("me => ERROR", error);
|
||||||
|
this.castErrorToResponse(error, res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param email
|
||||||
|
* @param playUri
|
||||||
|
* @param IPAddress
|
||||||
|
* @return FetchMemberDataByUuidResponse|object
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private async getUserByUserIdentifier(
|
||||||
|
email: string,
|
||||||
|
playUri: string,
|
||||||
|
IPAddress: string
|
||||||
|
): Promise<FetchMemberDataByUuidResponse | object> {
|
||||||
|
let data: FetchMemberDataByUuidResponse = {
|
||||||
|
email: email,
|
||||||
|
userUuid: email,
|
||||||
|
tags: [],
|
||||||
|
messages: [],
|
||||||
|
visitCardUrl: null,
|
||||||
|
textures: [],
|
||||||
|
userRoomToken: undefined,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
data = await adminApi.fetchMemberDataByUuid(email, playUri, IPAddress, []);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("openIDCallback => fetchMemberDataByUuid", err);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import {
|
|||||||
ItemEventMessage,
|
ItemEventMessage,
|
||||||
ViewportMessage,
|
ViewportMessage,
|
||||||
ClientToServerMessage,
|
ClientToServerMessage,
|
||||||
SilentMessage,
|
|
||||||
WebRtcSignalToServerMessage,
|
WebRtcSignalToServerMessage,
|
||||||
PlayGlobalMessage,
|
PlayGlobalMessage,
|
||||||
ReportPlayerMessage,
|
ReportPlayerMessage,
|
||||||
@ -525,8 +524,6 @@ export class IoSocketController {
|
|||||||
client,
|
client,
|
||||||
message.getSetplayerdetailsmessage() as SetPlayerDetailsMessage
|
message.getSetplayerdetailsmessage() as SetPlayerDetailsMessage
|
||||||
);
|
);
|
||||||
} else if (message.hasSilentmessage()) {
|
|
||||||
socketManager.handleSilentMessage(client, message.getSilentmessage() as SilentMessage);
|
|
||||||
} else if (message.hasItemeventmessage()) {
|
} else if (message.hasItemeventmessage()) {
|
||||||
socketManager.handleItemEvent(client, message.getItemeventmessage() as ItemEventMessage);
|
socketManager.handleItemEvent(client, message.getItemeventmessage() as ItemEventMessage);
|
||||||
} else if (message.hasVariablemessage()) {
|
} else if (message.hasVariablemessage()) {
|
||||||
|
@ -18,6 +18,7 @@ import {
|
|||||||
ErrorMessage,
|
ErrorMessage,
|
||||||
PlayerDetailsUpdatedMessage,
|
PlayerDetailsUpdatedMessage,
|
||||||
SetPlayerDetailsMessage,
|
SetPlayerDetailsMessage,
|
||||||
|
AvailabilityStatus,
|
||||||
} from "../Messages/generated/messages_pb";
|
} from "../Messages/generated/messages_pb";
|
||||||
import { ClientReadableStream } from "grpc";
|
import { ClientReadableStream } from "grpc";
|
||||||
import { PositionDispatcher } from "../Model/PositionDispatcher";
|
import { PositionDispatcher } from "../Model/PositionDispatcher";
|
||||||
@ -49,7 +50,7 @@ export class UserDescriptor {
|
|||||||
private name: string,
|
private name: string,
|
||||||
private characterLayers: CharacterLayerMessage[],
|
private characterLayers: CharacterLayerMessage[],
|
||||||
private position: PositionMessage,
|
private position: PositionMessage,
|
||||||
private away: boolean,
|
private status: AvailabilityStatus,
|
||||||
private visitCardUrl: string | null,
|
private visitCardUrl: string | null,
|
||||||
private companion?: CompanionMessage,
|
private companion?: CompanionMessage,
|
||||||
private outlineColor?: number
|
private outlineColor?: number
|
||||||
@ -70,7 +71,7 @@ export class UserDescriptor {
|
|||||||
message.getName(),
|
message.getName(),
|
||||||
message.getCharacterlayersList(),
|
message.getCharacterlayersList(),
|
||||||
position,
|
position,
|
||||||
message.getAway(),
|
message.getStatus(),
|
||||||
message.getVisitcardurl(),
|
message.getVisitcardurl(),
|
||||||
message.getCompanion(),
|
message.getCompanion(),
|
||||||
message.getHasoutline() ? message.getOutlinecolor() : undefined
|
message.getHasoutline() ? message.getOutlinecolor() : undefined
|
||||||
@ -91,9 +92,9 @@ export class UserDescriptor {
|
|||||||
} else {
|
} else {
|
||||||
this.outlineColor = playerDetails.getOutlinecolor()?.getValue();
|
this.outlineColor = playerDetails.getOutlinecolor()?.getValue();
|
||||||
}
|
}
|
||||||
const away = playerDetails.getAway();
|
const status = playerDetails.getStatus();
|
||||||
if (away) {
|
if (status !== undefined) {
|
||||||
this.away = away.getValue();
|
this.status = status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +105,7 @@ export class UserDescriptor {
|
|||||||
userJoinedMessage.setName(this.name);
|
userJoinedMessage.setName(this.name);
|
||||||
userJoinedMessage.setCharacterlayersList(this.characterLayers);
|
userJoinedMessage.setCharacterlayersList(this.characterLayers);
|
||||||
userJoinedMessage.setPosition(this.position);
|
userJoinedMessage.setPosition(this.position);
|
||||||
userJoinedMessage.setAway(this.away);
|
userJoinedMessage.setStatus(this.status);
|
||||||
if (this.visitCardUrl) {
|
if (this.visitCardUrl) {
|
||||||
userJoinedMessage.setVisitcardurl(this.visitCardUrl);
|
userJoinedMessage.setVisitcardurl(this.visitCardUrl);
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ import {
|
|||||||
ServerToAdminClientMessage,
|
ServerToAdminClientMessage,
|
||||||
ServerToClientMessage,
|
ServerToClientMessage,
|
||||||
SetPlayerDetailsMessage,
|
SetPlayerDetailsMessage,
|
||||||
SilentMessage,
|
|
||||||
SubMessage,
|
SubMessage,
|
||||||
UserJoinedRoomMessage,
|
UserJoinedRoomMessage,
|
||||||
UserLeftMessage,
|
UserLeftMessage,
|
||||||
@ -367,13 +366,6 @@ export class SocketManager implements ZoneEventListener {
|
|||||||
client.backConnection.write(pusherToBackMessage);
|
client.backConnection.write(pusherToBackMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSilentMessage(client: ExSocketInterface, silentMessage: SilentMessage) {
|
|
||||||
const pusherToBackMessage = new PusherToBackMessage();
|
|
||||||
pusherToBackMessage.setSilentmessage(silentMessage);
|
|
||||||
|
|
||||||
client.backConnection.write(pusherToBackMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleItemEvent(client: ExSocketInterface, itemEventMessage: ItemEventMessage) {
|
handleItemEvent(client: ExSocketInterface, itemEventMessage: ItemEventMessage) {
|
||||||
const pusherToBackMessage = new PusherToBackMessage();
|
const pusherToBackMessage = new PusherToBackMessage();
|
||||||
pusherToBackMessage.setItemeventmessage(itemEventMessage);
|
pusherToBackMessage.setItemeventmessage(itemEventMessage);
|
||||||
|