Merge remote-tracking branch 'upstream/develop' into main

This commit is contained in:
_Bastler 2021-03-23 14:24:49 +01:00
commit c8127b3c54
11 changed files with 237 additions and 79 deletions

View File

@ -1,4 +1,4 @@
![](https://github.com/thecodingmachine/workadventure/workflows/Continuous%20Integration/badge.svg) ![](https://github.com/thecodingmachine/workadventure/workflows/Continuous%20Integration/badge.svg) [![Discord](https://img.shields.io/discord/821338762134290432?label=Discord)](https://discord.gg/JVVhXzcE)
![WorkAdventure landscape image](README-INTRO.jpg) ![WorkAdventure landscape image](README-INTRO.jpg)

View File

@ -98,12 +98,12 @@
</svg> </svg>
</button> </button>
<div class="audioplayer"> <div class="audioplayer">
<input type="range" id="audioplayer_volume" min="0" max="1" step="0.05" value="1" /> <input type="range" id="audioplayer_volume" min="0" max="1" step="0.025" value="1" />
</div> </div>
</div> </div>
<div class="audioplayer"> <div class="audioplayer">
<label id="label-audioplayer_decrease_while_talking" for="audiooplayer_decrease_while_talking" title="decrease background volume by 50% when entering conversations"> <label id="label-audioplayer_decrease_while_talking" for="audiooplayer_decrease_while_talking" title="decrease background volume by 50% when entering conversations">
autoreduce reduce in conversations
<input type="checkbox" id="audioplayer_decrease_while_talking" checked /> <input type="checkbox" id="audioplayer_decrease_while_talking" checked />
</label> </label>
<div id="audioplayer" style="visibility: hidden"></div> <div id="audioplayer" style="visibility: hidden"></div>

View File

@ -363,10 +363,14 @@ body {
justify-content: center; justify-content: center;
} }
.audioplayer > div {
padding-right: 1.2rem;
}
#audioplayerctrl { #audioplayerctrl {
position: fixed; position: fixed;
top: 0; top: 0;
right: 50%; right: calc(50% - 120px);
padding: 0.3rem 0.5rem; padding: 0.3rem 0.5rem;
color: white; color: white;
transition: transform 0.5s; transition: transform 0.5s;

View File

@ -1,12 +1,15 @@
import {LocalUser} from "./LocalUser"; import {LocalUser} from "./LocalUser";
const characterLayersKey = 'characterLayers'; const playerNameKey = 'playerName';
const gameQualityKey = 'gameQuality'; const selectedPlayerKey = 'selectedPlayer';
const videoQualityKey = 'videoQuality'; const customCursorPositionKey = 'customCursorPosition';
const characterLayersKey = 'characterLayers';
const gameQualityKey = 'gameQuality';
const videoQualityKey = 'videoQuality';
const audioPlayerVolumeKey = 'audioVolume';
const audioPlayerMuteKey = 'audioMute';
//todo: add localstorage fallback
class LocalUserStore { class LocalUserStore {
saveUser(localUser: LocalUser) { saveUser(localUser: LocalUser) {
localStorage.setItem('localUser', JSON.stringify(localUser)); localStorage.setItem('localUser', JSON.stringify(localUser));
} }
@ -16,46 +19,60 @@ class LocalUserStore {
} }
setName(name:string): void { setName(name:string): void {
window.localStorage.setItem('playerName', name); localStorage.setItem(playerNameKey, name);
} }
getName(): string { getName(): string {
return window.localStorage.getItem('playerName') ?? ''; return localStorage.getItem(playerNameKey) || '';
} }
setPlayerCharacterIndex(playerCharacterIndex: number): void { setPlayerCharacterIndex(playerCharacterIndex: number): void {
window.localStorage.setItem('selectedPlayer', ''+playerCharacterIndex); localStorage.setItem(selectedPlayerKey, ''+playerCharacterIndex);
} }
getPlayerCharacterIndex(): number { getPlayerCharacterIndex(): number {
return parseInt(window.localStorage.getItem('selectedPlayer') || ''); return parseInt(localStorage.getItem(selectedPlayerKey) || '');
} }
setCustomCursorPosition(activeRow:number, selectedLayers: number[]): void { setCustomCursorPosition(activeRow:number, selectedLayers: number[]): void {
window.localStorage.setItem('customCursorPosition', JSON.stringify({activeRow, selectedLayers})); localStorage.setItem(customCursorPositionKey, JSON.stringify({activeRow, selectedLayers}));
} }
getCustomCursorPosition(): {activeRow:number, selectedLayers:number[]}|null { getCustomCursorPosition(): {activeRow:number, selectedLayers:number[]}|null {
return JSON.parse(window.localStorage.getItem('customCursorPosition') || "null"); return JSON.parse(localStorage.getItem(customCursorPositionKey) || "null");
} }
setCharacterLayers(layers: string[]): void { setCharacterLayers(layers: string[]): void {
window.localStorage.setItem(characterLayersKey, JSON.stringify(layers)); localStorage.setItem(characterLayersKey, JSON.stringify(layers));
} }
getCharacterLayers(): string[]|null { getCharacterLayers(): string[]|null {
return JSON.parse(window.localStorage.getItem(characterLayersKey) || "null"); return JSON.parse(localStorage.getItem(characterLayersKey) || "null");
} }
getGameQualityValue(): number {
return parseInt(window.localStorage.getItem(gameQualityKey) || '') || 60;
}
setGameQualityValue(value: number): void { setGameQualityValue(value: number): void {
localStorage.setItem(gameQualityKey, '' + value); localStorage.setItem(gameQualityKey, '' + value);
} }
getGameQualityValue(): number {
getVideoQualityValue(): number { return parseInt(localStorage.getItem(gameQualityKey) || '60');
return parseInt(window.localStorage.getItem(videoQualityKey) || '') || 20;
} }
setVideoQualityValue(value: number): void { setVideoQualityValue(value: number): void {
localStorage.setItem(videoQualityKey, '' + value); localStorage.setItem(videoQualityKey, '' + value);
} }
getVideoQualityValue(): number {
return parseInt(localStorage.getItem(videoQualityKey) || '20');
}
setAudioPlayerVolume(value: number): void {
localStorage.setItem(audioPlayerVolumeKey, '' + value);
}
getAudioPlayerVolume(): number {
return parseFloat(localStorage.getItem(audioPlayerVolumeKey) || '1');
}
setAudioPlayerMuted(value: boolean): void {
localStorage.setItem(audioPlayerMuteKey, value.toString());
}
getAudioPlayerMuted(): boolean {
return localStorage.getItem(audioPlayerMuteKey) === 'true';
}
} }
export const localUserStore = new LocalUserStore(); export const localUserStore = new LocalUserStore();

View File

@ -29,7 +29,9 @@ import {
ON_ACTION_TRIGGER_BUTTON, ON_ACTION_TRIGGER_BUTTON,
TRIGGER_JITSI_PROPERTIES, TRIGGER_JITSI_PROPERTIES,
TRIGGER_WEBSITE_PROPERTIES, TRIGGER_WEBSITE_PROPERTIES,
WEBSITE_MESSAGE_PROPERTIES WEBSITE_MESSAGE_PROPERTIES,
AUDIO_VOLUME_PROPERTY,
AUDIO_LOOP_PROPERTY
} from "../../WebRtc/LayoutManager"; } from "../../WebRtc/LayoutManager";
import {GameMap} from "./GameMap"; import {GameMap} from "./GameMap";
import {coWebsiteManager} from "../../WebRtc/CoWebsiteManager"; import {coWebsiteManager} from "../../WebRtc/CoWebsiteManager";
@ -455,16 +457,12 @@ export class GameScene extends ResizableScene implements CenterListener {
}); });
this.connection.onGroupUpdatedOrCreated((groupPositionMessage: GroupCreatedUpdatedMessageInterface) => { this.connection.onGroupUpdatedOrCreated((groupPositionMessage: GroupCreatedUpdatedMessageInterface) => {
audioManager.decreaseVolume();
this.shareGroupPosition(groupPositionMessage); this.shareGroupPosition(groupPositionMessage);
this.openChatIcon.setVisible(true);
}) })
this.connection.onGroupDeleted((groupId: number) => { this.connection.onGroupDeleted((groupId: number) => {
audioManager.restoreVolume();
try { try {
this.deleteGroup(groupId); this.deleteGroup(groupId);
this.openChatIcon.setVisible(false);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
@ -517,11 +515,15 @@ export class GameScene extends ResizableScene implements CenterListener {
onConnect(user: UserSimplePeerInterface) { onConnect(user: UserSimplePeerInterface) {
self.presentationModeSprite.setVisible(true); self.presentationModeSprite.setVisible(true);
self.chatModeSprite.setVisible(true); self.chatModeSprite.setVisible(true);
self.openChatIcon.setVisible(true);
audioManager.decreaseVolume();
}, },
onDisconnect(userId: number) { onDisconnect(userId: number) {
if (self.simplePeer.getNbConnections() === 0) { if (self.simplePeer.getNbConnections() === 0) {
self.presentationModeSprite.setVisible(false); self.presentationModeSprite.setVisible(false);
self.chatModeSprite.setVisible(false); self.chatModeSprite.setVisible(false);
self.openChatIcon.setVisible(false);
audioManager.restoreVolume();
} }
} }
}) })
@ -630,7 +632,8 @@ export class GameScene extends ResizableScene implements CenterListener {
}else{ }else{
const openJitsiRoomFunction = () => { const openJitsiRoomFunction = () => {
const roomName = jitsiFactory.getRoomName(newValue.toString(), this.instance); const roomName = jitsiFactory.getRoomName(newValue.toString(), this.instance);
if (JITSI_PRIVATE_MODE) { const jitsiUrl = allProps.get("jitsiUrl") as string|undefined;
if (JITSI_PRIVATE_MODE && !jitsiUrl) {
const adminTag = allProps.get("jitsiRoomAdminTag") as string|undefined; const adminTag = allProps.get("jitsiRoomAdminTag") as string|undefined;
this.connection.emitQueryJitsiJwtMessage(roomName, adminTag); this.connection.emitQueryJitsiJwtMessage(roomName, adminTag);
@ -661,14 +664,15 @@ export class GameScene extends ResizableScene implements CenterListener {
this.connection.setSilent(true); this.connection.setSilent(true);
} }
}); });
this.gameMap.onPropertyChange('playAudio', (newValue, oldValue) => { this.gameMap.onPropertyChange('playAudio', (newValue, oldValue, allProps) => {
newValue === undefined ? audioManager.unloadAudio() : audioManager.playAudio(newValue, this.getMapDirUrl()); const volume = allProps.get(AUDIO_VOLUME_PROPERTY) as number|undefined;
const loop = allProps.get(AUDIO_LOOP_PROPERTY) as boolean|undefined;
newValue === undefined ? audioManager.unloadAudio() : audioManager.playAudio(newValue, this.getMapDirUrl(), volume, loop);
}); });
// TODO: This legacy property should be removed at some point
this.gameMap.onPropertyChange('playAudioLoop', (newValue, oldValue) => { this.gameMap.onPropertyChange('playAudioLoop', (newValue, oldValue) => {
newValue === undefined ? audioManager.unloadAudio() : audioManager.playAudio(newValue, this.getMapDirUrl()); newValue === undefined ? audioManager.unloadAudio() : audioManager.playAudio(newValue, this.getMapDirUrl(), undefined, true);
}); });
} }
private getMapDirUrl(): string { private getMapDirUrl(): string {
@ -1206,8 +1210,9 @@ export class GameScene extends ResizableScene implements CenterListener {
const allProps = this.gameMap.getCurrentProperties(); const allProps = this.gameMap.getCurrentProperties();
const jitsiConfig = this.safeParseJSONstring(allProps.get("jitsiConfig") as string|undefined, 'jitsiConfig'); const jitsiConfig = this.safeParseJSONstring(allProps.get("jitsiConfig") as string|undefined, 'jitsiConfig');
const jitsiInterfaceConfig = this.safeParseJSONstring(allProps.get("jitsiInterfaceConfig") as string|undefined, 'jitsiInterfaceConfig'); const jitsiInterfaceConfig = this.safeParseJSONstring(allProps.get("jitsiInterfaceConfig") as string|undefined, 'jitsiInterfaceConfig');
const jitsiUrl = allProps.get("jitsiUrl") as string|undefined;
jitsiFactory.start(roomName, this.playerName, jwt, jitsiConfig, jitsiInterfaceConfig); jitsiFactory.start(roomName, this.playerName, jwt, jitsiConfig, jitsiInterfaceConfig, jitsiUrl);
this.connection.setSilent(true); this.connection.setSilent(true);
mediaManager.hideGameOverlay(); mediaManager.hideGameOverlay();

View File

@ -1,5 +1,6 @@
import {HtmlUtils} from "./HtmlUtils"; import {HtmlUtils} from "./HtmlUtils";
import {isUndefined} from "generic-type-guard"; import {isUndefined} from "generic-type-guard";
import {localUserStore} from "../Connexion/LocalUserStore";
enum audioStates { enum audioStates {
closed = 0, closed = 0,
@ -9,6 +10,8 @@ enum audioStates {
const audioPlayerDivId = "audioplayer"; const audioPlayerDivId = "audioplayer";
const audioPlayerCtrlId = "audioplayerctrl"; const audioPlayerCtrlId = "audioplayerctrl";
const audioPlayerVolId = "audioplayer_volume";
const audioPlayerMuteId = "audioplayer_volume_icon_playing";
const animationTime = 500; const animationTime = 500;
class AudioManager { class AudioManager {
@ -17,6 +20,8 @@ class AudioManager {
private audioPlayerDiv: HTMLDivElement; private audioPlayerDiv: HTMLDivElement;
private audioPlayerCtrl: HTMLDivElement; private audioPlayerCtrl: HTMLDivElement;
private audioPlayerElem: HTMLAudioElement | undefined; private audioPlayerElem: HTMLAudioElement | undefined;
private audioPlayerVol: HTMLInputElement;
private audioPlayerMute: HTMLInputElement;
private volume = 1; private volume = 1;
private muted = false; private muted = false;
@ -26,19 +31,19 @@ class AudioManager {
constructor() { constructor() {
this.audioPlayerDiv = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(audioPlayerDivId); this.audioPlayerDiv = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(audioPlayerDivId);
this.audioPlayerCtrl = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(audioPlayerCtrlId); this.audioPlayerCtrl = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(audioPlayerCtrlId);
this.audioPlayerVol = HtmlUtils.getElementByIdOrFail<HTMLInputElement>(audioPlayerVolId);
this.audioPlayerMute = HtmlUtils.getElementByIdOrFail<HTMLInputElement>(audioPlayerMuteId);
const storedVolume = localStorage.getItem('volume') this.volume = localUserStore.getAudioPlayerVolume();
if (storedVolume === null) { this.audioPlayerVol.value = '' + this.volume;
this.setVolume(1);
} else { this.muted = localUserStore.getAudioPlayerMuted();
this.volume = parseFloat(storedVolume); if (this.muted) {
HtmlUtils.getElementByIdOrFail<HTMLInputElement>('audioplayer_volume').value = storedVolume; this.audioPlayerMute.classList.add('muted');
} }
HtmlUtils.getElementByIdOrFail<HTMLInputElement>('audioplayer_volume').value = '' + this.volume;
} }
public playAudio(url: string|number|boolean, mapDirUrl: string, loop=false): void { public playAudio(url: string|number|boolean, mapDirUrl: string, volume: number|undefined, loop=false): void {
const audioPath = url as string; const audioPath = url as string;
let realAudioPath = ''; let realAudioPath = '';
@ -50,7 +55,7 @@ class AudioManager {
realAudioPath = mapDirUrl + '/' + url; realAudioPath = mapDirUrl + '/' + url;
} }
this.loadAudio(realAudioPath); this.loadAudio(realAudioPath, volume);
if (loop) { if (loop) {
this.loop(); this.loop();
@ -75,26 +80,29 @@ class AudioManager {
} }
private changeVolume(talking = false): void { private changeVolume(talking = false): void {
if (!isUndefined(this.audioPlayerElem)) { if (isUndefined(this.audioPlayerElem)) {
this.audioPlayerElem.volume = this.naturalVolume(talking && this.decreaseWhileTalking); return;
this.audioPlayerElem.muted = this.muted;
} }
}
private naturalVolume(makeSofter: boolean = false): number { const reduceVolume = talking && this.decreaseWhileTalking;
const volume = this.volume if (reduceVolume && !this.volumeReduced) {
const retVol = makeSofter && !this.volumeReduced ? Math.pow(volume * 0.5, 3) : volume this.volume *= 0.5;
this.volumeReduced = makeSofter } else if (!reduceVolume && this.volumeReduced) {
return retVol; this.volume *= 2.0;
}
this.volumeReduced = reduceVolume;
this.audioPlayerElem.volume = this.volume;
this.audioPlayerVol.value = '' + this.volume;
this.audioPlayerElem.muted = this.muted;
} }
private setVolume(volume: number): void { private setVolume(volume: number): void {
this.volume = volume; this.volume = volume;
localStorage.setItem('volume', '' + volume); localUserStore.setAudioPlayerVolume(volume);
} }
private loadAudio(url: string, volume: number|undefined): void {
private loadAudio(url: string): void {
this.load(); this.load();
/* Solution 1, remove whole audio player */ /* Solution 1, remove whole audio player */
@ -112,23 +120,24 @@ class AudioManager {
this.audioPlayerElem.append(srcElem); this.audioPlayerElem.append(srcElem);
this.audioPlayerDiv.append(this.audioPlayerElem); this.audioPlayerDiv.append(this.audioPlayerElem);
this.volume = volume ? Math.min(volume, this.volume) : this.volume;
this.changeVolume(); this.changeVolume();
this.audioPlayerElem.play(); this.audioPlayerElem.play();
const muteElem = HtmlUtils.getElementByIdOrFail<HTMLInputElement>('audioplayer_mute'); const muteElem = HtmlUtils.getElementByIdOrFail<HTMLInputElement>('audioplayer_mute');
muteElem.onclick = (ev: Event)=> { muteElem.onclick = (ev: Event) => {
this.muted = !this.muted; this.muted = !this.muted;
this.changeVolume(); this.changeVolume();
localUserStore.setAudioPlayerMuted(this.muted);
if (this.muted) { if (this.muted) {
HtmlUtils.getElementByIdOrFail<HTMLInputElement>('audioplayer_volume_icon_playing').classList.add('muted'); this.audioPlayerMute.classList.add('muted');
} else { } else {
HtmlUtils.getElementByIdOrFail<HTMLInputElement>('audioplayer_volume_icon_playing').classList.remove('muted'); this.audioPlayerMute.classList.remove('muted');
} }
} }
const volumeElem = HtmlUtils.getElementByIdOrFail<HTMLInputElement>('audioplayer_volume'); this.audioPlayerVol.oninput = (ev: Event)=> {
volumeElem.oninput = (ev: Event)=> {
this.setVolume(parseFloat((<HTMLInputElement>ev.currentTarget).value)); this.setVolume(parseFloat((<HTMLInputElement>ev.currentTarget).value));
this.changeVolume(); this.changeVolume();

View File

@ -72,6 +72,7 @@ class JitsiFactory {
private audioCallback = this.onAudioChange.bind(this); private audioCallback = this.onAudioChange.bind(this);
private videoCallback = this.onVideoChange.bind(this); private videoCallback = this.onVideoChange.bind(this);
private previousConfigMeet? : jitsiConfigInterface; private previousConfigMeet? : jitsiConfigInterface;
private jitsiScriptLoaded: boolean = false;
/** /**
* Slugifies the room name and prepends the room name with the instance * Slugifies the room name and prepends the room name with the instance
@ -80,11 +81,11 @@ class JitsiFactory {
return slugify(instance.replace('/', '-') + "-" + roomName); return slugify(instance.replace('/', '-') + "-" + roomName);
} }
public start(roomName: string, playerName:string, jwt?: string, config?: object, interfaceConfig?: object): void { public start(roomName: string, playerName:string, jwt?: string, config?: object, interfaceConfig?: object, jitsiUrl?: string): void {
//save previous config //save previous config
this.previousConfigMeet = getDefaultConfig(); this.previousConfigMeet = getDefaultConfig();
coWebsiteManager.insertCoWebsite((cowebsiteDiv => { coWebsiteManager.insertCoWebsite((async cowebsiteDiv => {
// Jitsi meet external API maintains some data in local storage // Jitsi meet external API maintains some data in local storage
// which is sent via the appData URL parameter when joining a // which is sent via the appData URL parameter when joining a
// conference. Problem is that this data grows indefinitely. Thus // conference. Problem is that this data grows indefinitely. Thus
@ -93,7 +94,12 @@ class JitsiFactory {
// clear jitsi local storage before starting a new conference. // clear jitsi local storage before starting a new conference.
window.localStorage.removeItem("jitsiLocalStorage"); window.localStorage.removeItem("jitsiLocalStorage");
const domain = JITSI_URL; const domain = jitsiUrl || JITSI_URL;
if (domain === undefined) {
throw new Error('Missing JITSI_URL environment variable or jitsiUrl parameter in the map.')
}
await this.loadJitsiScript(domain);
const options: any = { // eslint-disable-line @typescript-eslint/no-explicit-any const options: any = { // eslint-disable-line @typescript-eslint/no-explicit-any
roomName: roomName, roomName: roomName,
jwt: jwt, jwt: jwt,
@ -157,6 +163,32 @@ class JitsiFactory {
mediaManager.enableCamera(); mediaManager.enableCamera();
} }
} }
private async loadJitsiScript(domain: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
if (this.jitsiScriptLoaded) {
resolve();
return;
}
this.jitsiScriptLoaded = true;
// Load Jitsi if the environment variable is set.
const jitsiScript = document.createElement('script');
jitsiScript.src = 'https://' + domain + '/external_api.js';
jitsiScript.onload = () => {
resolve();
}
jitsiScript.onerror = () => {
reject();
}
document.head.appendChild(jitsiScript);
})
}
} }
export const jitsiFactory = new JitsiFactory(); export const jitsiFactory = new JitsiFactory();

View File

@ -31,6 +31,9 @@ export const TRIGGER_JITSI_PROPERTIES = 'jitsiTrigger';
export const WEBSITE_MESSAGE_PROPERTIES = 'openWebsiteTriggerMessage'; export const WEBSITE_MESSAGE_PROPERTIES = 'openWebsiteTriggerMessage';
export const JITSI_MESSAGE_PROPERTIES = 'jitsiTriggerMessage'; export const JITSI_MESSAGE_PROPERTIES = 'jitsiTriggerMessage';
export const AUDIO_VOLUME_PROPERTY = 'audioVolume';
export const AUDIO_LOOP_PROPERTY = 'audioLoop';
/** /**
* This class is in charge of the video-conference layout. * This class is in charge of the video-conference layout.
* It receives positioning requests for videos and does its best to place them on the screen depending on the active layout mode. * It receives positioning requests for videos and does its best to place them on the screen depending on the active layout mode.

View File

@ -63,7 +63,7 @@ export class SimplePeer {
} }
public getNbConnections(): number { public getNbConnections(): number {
return this.PeerConnectionArray.size; return this.Users.length;
} }
/** /**
@ -230,9 +230,6 @@ export class SimplePeer {
this.closeScreenSharingConnection(userId); this.closeScreenSharingConnection(userId);
for (const peerConnectionListener of this.peerConnectionListeners) {
peerConnectionListener.onDisconnect(userId);
}
const userIndex = this.Users.findIndex(user => user.userId === userId); const userIndex = this.Users.findIndex(user => user.userId === userId);
if(userIndex < 0){ if(userIndex < 0){
throw 'Couln\'t delete user'; throw 'Couln\'t delete user';
@ -250,6 +247,10 @@ export class SimplePeer {
this.PeerScreenSharingConnectionArray.delete(userId); this.PeerScreenSharingConnectionArray.delete(userId);
} }
} }
for (const peerConnectionListener of this.peerConnectionListeners) {
peerConnectionListener.onDisconnect(userId);
}
} }
/** /**

View File

@ -16,13 +16,6 @@ import {HelpCameraSettingsScene} from "./Phaser/Menu/HelpCameraSettingsScene";
import {localUserStore} from "./Connexion/LocalUserStore"; import {localUserStore} from "./Connexion/LocalUserStore";
import {ErrorScene} from "./Phaser/Reconnecting/ErrorScene"; import {ErrorScene} from "./Phaser/Reconnecting/ErrorScene";
// Load Jitsi if the environment variable is set.
if (JITSI_URL) {
const jitsiScript = document.createElement('script');
jitsiScript.src = 'https://' + JITSI_URL + '/external_api.js';
document.head.appendChild(jitsiScript);
}
const {width, height} = coWebsiteManager.getGameSize(); const {width, height} = coWebsiteManager.getGameSize();
const valueGameQuality = localUserStore.getGameQualityValue(); const valueGameQuality = localUserStore.getGameQualityValue();

View File

@ -0,0 +1,94 @@
{ "compressionlevel":-1,
"editorsettings":
{
"export":
{
"target":"."
}
},
"height":10,
"infinite":false,
"layers":[
{
"data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
"height":10,
"id":1,
"name":"floor",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":10,
"x":0,
"y":0
},
{
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"height":10,
"id":2,
"name":"start",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":10,
"x":0,
"y":0
},
{
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 34, 34, 34, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"height":10,
"id":5,
"name":"jitsiConf",
"opacity":1,
"properties":[
{
"name":"jitsiRoom",
"type":"string",
"value":"myRoom"
},
{
"name":"jitsiUrl",
"type":"string",
"value":"meet.jit.si"
}],
"type":"tilelayer",
"visible":true,
"width":10,
"x":0,
"y":0
},
{
"draworder":"topdown",
"id":3,
"name":"floorLayer",
"objects":[],
"opacity":1,
"type":"objectgroup",
"visible":true,
"x":0,
"y":0
}],
"nextlayerid":6,
"nextobjectid":1,
"orientation":"orthogonal",
"renderorder":"right-down",
"tiledversion":"1.3.3",
"tileheight":32,
"tilesets":[
{
"columns":11,
"firstgid":1,
"image":"tileset1.png",
"imageheight":352,
"imagewidth":352,
"margin":0,
"name":"tileset1",
"spacing":0,
"tilecount":121,
"tileheight":32,
"tilewidth":32
}],
"tilewidth":32,
"type":"map",
"version":1.2,
"width":10
}