Merge branch 'develop' of github.com:thecodingmachine/workadventure into GlobalMessageToWorld
This commit is contained in:
commit
bd96a32d5b
@ -33,7 +33,7 @@
|
|||||||
- Use `WA.state.[any variable]: unknown` to access directly any variable (this is a shortcut to using `WA.state.loadVariable` and `WA.state.saveVariable`)
|
- Use `WA.state.[any variable]: unknown` to access directly any variable (this is a shortcut to using `WA.state.loadVariable` and `WA.state.saveVariable`)
|
||||||
- Users blocking now relies on UUID rather than ID. A blocked user that leaves a room and comes back will stay blocked.
|
- Users blocking now relies on UUID rather than ID. A blocked user that leaves a room and comes back will stay blocked.
|
||||||
- The text chat was redesigned to be prettier and to use more features :
|
- The text chat was redesigned to be prettier and to use more features :
|
||||||
- The chat is now persistent bewteen discussions and always accesible
|
- The chat is now persistent between discussions and always accessible
|
||||||
- The chat now tracks incoming and outcoming users in your conversation
|
- The chat now tracks incoming and outcoming users in your conversation
|
||||||
- The chat allows your to see the visit card of users
|
- The chat allows your to see the visit card of users
|
||||||
- You can close the chat window with the escape key
|
- You can close the chat window with the escape key
|
||||||
|
@ -104,6 +104,15 @@ export class GameRoom {
|
|||||||
public getUserById(id: number): User | undefined {
|
public getUserById(id: number): User | undefined {
|
||||||
return this.users.get(id);
|
return this.users.get(id);
|
||||||
}
|
}
|
||||||
|
public getUsersByUuid(uuid: string): User[] {
|
||||||
|
const userList: User[] = [];
|
||||||
|
for (const user of this.users.values()) {
|
||||||
|
if (user.uuid === uuid) {
|
||||||
|
userList.push(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return userList;
|
||||||
|
}
|
||||||
|
|
||||||
public join(socket: UserSocket, joinRoomMessage: JoinRoomMessage): User {
|
public join(socket: UserSocket, joinRoomMessage: JoinRoomMessage): User {
|
||||||
const positionMessage = joinRoomMessage.getPositionmessage();
|
const positionMessage = joinRoomMessage.getPositionmessage();
|
||||||
|
@ -21,7 +21,7 @@ interface ZoneDescriptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PositionNotifier {
|
export class PositionNotifier {
|
||||||
// TODO: we need a way to clean the zones if noone is in the zone and noone listening (to free memory!)
|
// TODO: we need a way to clean the zones if no one is in the zone and no one listening (to free memory!)
|
||||||
|
|
||||||
private zones: Zone[][] = [];
|
private zones: Zone[][] = [];
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ const roomManager: IRoomManagerServer = {
|
|||||||
room = gameRoom;
|
room = gameRoom;
|
||||||
user = myUser;
|
user = myUser;
|
||||||
} else {
|
} else {
|
||||||
//Connexion may have been closed before the init was finished, so we have to manually disconnect the user.
|
//Connection may have been closed before the init was finished, so we have to manually disconnect the user.
|
||||||
socketManager.leaveRoom(gameRoom, myUser);
|
socketManager.leaveRoom(gameRoom, myUser);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -701,8 +701,8 @@ export class SocketManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const recipient = room.getUserByUuid(recipientUuid);
|
const recipients = room.getUsersByUuid(recipientUuid);
|
||||||
if (recipient === undefined) {
|
if (recipients.length === 0) {
|
||||||
console.error(
|
console.error(
|
||||||
"In sendAdminMessage, could not find user with id '" +
|
"In sendAdminMessage, could not find user with id '" +
|
||||||
recipientUuid +
|
recipientUuid +
|
||||||
@ -711,14 +711,16 @@ export class SocketManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendUserMessage = new SendUserMessage();
|
for (const recipient of recipients) {
|
||||||
sendUserMessage.setMessage(message);
|
const sendUserMessage = new SendUserMessage();
|
||||||
sendUserMessage.setType("ban"); //todo: is the type correct?
|
sendUserMessage.setMessage(message);
|
||||||
|
sendUserMessage.setType("ban"); //todo: is the type correct?
|
||||||
|
|
||||||
const serverToClientMessage = new ServerToClientMessage();
|
const serverToClientMessage = new ServerToClientMessage();
|
||||||
serverToClientMessage.setSendusermessage(sendUserMessage);
|
serverToClientMessage.setSendusermessage(sendUserMessage);
|
||||||
|
|
||||||
recipient.socket.write(serverToClientMessage);
|
recipient.socket.write(serverToClientMessage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async banUser(roomId: string, recipientUuid: string, message: string): Promise<void> {
|
public async banUser(roomId: string, recipientUuid: string, message: string): Promise<void> {
|
||||||
@ -732,8 +734,8 @@ export class SocketManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const recipient = room.getUserByUuid(recipientUuid);
|
const recipients = room.getUsersByUuid(recipientUuid);
|
||||||
if (recipient === undefined) {
|
if (recipients.length === 0) {
|
||||||
console.error(
|
console.error(
|
||||||
"In banUser, could not find user with id '" +
|
"In banUser, could not find user with id '" +
|
||||||
recipientUuid +
|
recipientUuid +
|
||||||
@ -742,19 +744,21 @@ export class SocketManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's leave the room now.
|
for (const recipient of recipients) {
|
||||||
room.leave(recipient);
|
// Let's leave the room now.
|
||||||
|
room.leave(recipient);
|
||||||
|
|
||||||
const banUserMessage = new BanUserMessage();
|
const banUserMessage = new BanUserMessage();
|
||||||
banUserMessage.setMessage(message);
|
banUserMessage.setMessage(message);
|
||||||
banUserMessage.setType("banned");
|
banUserMessage.setType("banned");
|
||||||
|
|
||||||
const serverToClientMessage = new ServerToClientMessage();
|
const serverToClientMessage = new ServerToClientMessage();
|
||||||
serverToClientMessage.setBanusermessage(banUserMessage);
|
serverToClientMessage.setBanusermessage(banUserMessage);
|
||||||
|
|
||||||
// Let's close the connection when the user is banned.
|
// Let's close the connection when the user is banned.
|
||||||
recipient.socket.write(serverToClientMessage);
|
recipient.socket.write(serverToClientMessage);
|
||||||
recipient.socket.end();
|
recipient.socket.end();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendAdminRoomMessage(roomId: string, message: string, type: string) {
|
async sendAdminRoomMessage(roomId: string, message: string, type: string) {
|
||||||
|
35
docs/maps/text.md
Normal file
35
docs/maps/text.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{.section-title.accent.text-primary}
|
||||||
|
# Writing text on a map
|
||||||
|
|
||||||
|
## Solution 1: design a specific tileset (recommended)
|
||||||
|
|
||||||
|
If you want to write some text on a map, our recommendation is to create a tileset that contains
|
||||||
|
your text. You will obtain the most pleasant graphical result with this result, since you will be able
|
||||||
|
to control the fonts you use, and you will be able to disable the antialiasing of the font to get a
|
||||||
|
"crispy" result easily.
|
||||||
|
|
||||||
|
## Solution 2: using a "text" object in Tiled
|
||||||
|
|
||||||
|
On "object" layers, Tiled has support for "Text" objects. You can use these objects to add some
|
||||||
|
text on your map.
|
||||||
|
|
||||||
|
WorkAdventure will do its best to display the text properly. However, you need to know that:
|
||||||
|
|
||||||
|
- Tiled displays your system fonts.
|
||||||
|
- Computers have different sets of fonts. Therefore, browsers never rely on system fonts
|
||||||
|
- Which means if you select a font in Tiled, it is quite unlikely it will render properly in WorkAdventure
|
||||||
|
|
||||||
|
To circumvent this problem, in your text object in Tiled, you can add an additional property: `font-family`.
|
||||||
|
|
||||||
|
The `font-family` property can contain any "web-font" that can be loaded by your browser.
|
||||||
|
|
||||||
|
{.alert.alert-info}
|
||||||
|
**Pro-tip:** By default, WorkAdventure uses the **'"Press Start 2P"'** font, which is a great pixelated
|
||||||
|
font that has support for a variety of accents. It renders great when used at *8px* size.
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<figure class="figure">
|
||||||
|
<img src="https://workadventu.re/img/docs/text-object.png" class="figure-img img-fluid rounded" alt="" style="width: 70%" />
|
||||||
|
<figcaption class="figure-caption">The "font-family" property</figcaption>
|
||||||
|
</figure>
|
||||||
|
</div>
|
@ -56,7 +56,7 @@ A few things to notice:
|
|||||||
|
|
||||||
## Building walls and "collidable" areas
|
## Building walls and "collidable" areas
|
||||||
|
|
||||||
By default, the characters can traverse any tiles. If you want to prevent your characeter from going through a tile (like a wall or a desktop), you must make this tile "collidable". You can do this by settings the `collides` property on a given tile.
|
By default, the characters can traverse any tiles. If you want to prevent your character from going through a tile (like a wall or a desktop), you must make this tile "collidable". You can do this by settings the `collides` property on a given tile.
|
||||||
|
|
||||||
To make a tile "collidable", you should:
|
To make a tile "collidable", you should:
|
||||||
|
|
||||||
|
1
front/dist/index.tmpl.html
vendored
1
front/dist/index.tmpl.html
vendored
@ -34,6 +34,7 @@
|
|||||||
<title>WorkAdventure</title>
|
<title>WorkAdventure</title>
|
||||||
</head>
|
</head>
|
||||||
<body id="body" style="margin: 0; background-color: #000">
|
<body id="body" style="margin: 0; background-color: #000">
|
||||||
|
|
||||||
<div class="main-container" id="main-container">
|
<div class="main-container" id="main-container">
|
||||||
<!-- Create the editor container -->
|
<!-- Create the editor container -->
|
||||||
<div id="game" class="game">
|
<div id="game" class="game">
|
||||||
|
62
front/dist/resources/service-worker.html
vendored
Normal file
62
front/dist/resources/service-worker.html
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport"
|
||||||
|
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
|
||||||
|
<!-- TRACK CODE -->
|
||||||
|
<!-- END TRACK CODE -->
|
||||||
|
|
||||||
|
<link rel="apple-touch-icon" sizes="57x57" href="/static/images/favicons/apple-icon-57x57.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="60x60" href="/static/images/favicons/apple-icon-60x60.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="72x72" href="/static/images/favicons/apple-icon-72x72.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="76x76" href="/static/images/favicons/apple-icon-76x76.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="114x114" href="/static/images/favicons/apple-icon-114x114.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="120x120" href="/static/images/favicons/apple-icon-120x120.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="144x144" href="/static/images/favicons/apple-icon-144x144.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="152x152" href="/static/images/favicons/apple-icon-152x152.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/static/images/favicons/apple-icon-180x180.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="192x192" href="/static/images/favicons/android-icon-192x192.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/static/images/favicons/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="96x96" href="/static/images/favicons/favicon-96x96.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/static/images/favicons/favicon-16x16.png">
|
||||||
|
<meta name="msapplication-TileColor" content="#000000">
|
||||||
|
<meta name="msapplication-TileImage" content="/static/images/favicons/ms-icon-144x144.png">
|
||||||
|
<meta name="theme-color" content="#000000">
|
||||||
|
|
||||||
|
<title>WorkAdventure PWA</title>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body{
|
||||||
|
font-family: Whitney, Lato, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
|
}
|
||||||
|
body img{
|
||||||
|
position: absolute;
|
||||||
|
top: calc( 50% - 25px);
|
||||||
|
height: 59px;
|
||||||
|
width: 307px;
|
||||||
|
left: calc( 50% - 150px);
|
||||||
|
}
|
||||||
|
body p{
|
||||||
|
position: absolute;
|
||||||
|
text-align: center;
|
||||||
|
top: calc( 50% + 50px);
|
||||||
|
left: calc( 50% - 150px);
|
||||||
|
height: 59px;
|
||||||
|
width: 307px;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="/static/images/logo.png" alt="WorkAdventure logo"/>
|
||||||
|
<p>Charging your workspace ...</p>
|
||||||
|
<script>
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location = localStorage.getItem('lastRoomUrl');
|
||||||
|
}, 4000);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
12
front/dist/resources/service-worker.js
vendored
12
front/dist/resources/service-worker.js
vendored
@ -48,6 +48,14 @@ self.addEventListener('fetch', function(event) {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.addEventListener('activate', function(event) {
|
self.addEventListener('wait', function(event) {
|
||||||
//TODO activate service worker
|
//TODO wait
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('update', function(event) {
|
||||||
|
//TODO update
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('beforeinstallprompt', (e) => {
|
||||||
|
//TODO change prompt
|
||||||
});
|
});
|
@ -128,11 +128,12 @@
|
|||||||
"type": "image\/png"
|
"type": "image\/png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"start_url": "/",
|
"start_url": "/resources/service-worker.html",
|
||||||
"background_color": "#000000",
|
"background_color": "#000000",
|
||||||
"display_override": ["window-control-overlay", "minimal-ui"],
|
"display_override": ["window-control-overlay", "minimal-ui"],
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"scope": "/",
|
"orientation": "portrait-primary",
|
||||||
|
"scope": "/resources/",
|
||||||
"lang": "en",
|
"lang": "en",
|
||||||
"theme_color": "#000000",
|
"theme_color": "#000000",
|
||||||
"shortcuts": [
|
"shortcuts": [
|
||||||
|
@ -3,9 +3,12 @@
|
|||||||
import { chatMessagesStore, chatVisibilityStore } from "../../Stores/ChatStore";
|
import { chatMessagesStore, chatVisibilityStore } from "../../Stores/ChatStore";
|
||||||
import ChatMessageForm from './ChatMessageForm.svelte';
|
import ChatMessageForm from './ChatMessageForm.svelte';
|
||||||
import ChatElement from './ChatElement.svelte';
|
import ChatElement from './ChatElement.svelte';
|
||||||
import { afterUpdate, beforeUpdate } from "svelte";
|
import {afterUpdate, beforeUpdate} from "svelte";
|
||||||
|
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
||||||
|
|
||||||
let listDom: HTMLElement;
|
let listDom: HTMLElement;
|
||||||
|
let chatWindowElement: HTMLElement;
|
||||||
|
let handleFormBlur: { blur():void };
|
||||||
let autoscroll: boolean;
|
let autoscroll: boolean;
|
||||||
|
|
||||||
beforeUpdate(() => {
|
beforeUpdate(() => {
|
||||||
@ -16,6 +19,12 @@
|
|||||||
if (autoscroll) listDom.scrollTo(0, listDom.scrollHeight);
|
if (autoscroll) listDom.scrollTo(0, listDom.scrollHeight);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function onClick(event: MouseEvent) {
|
||||||
|
if (HtmlUtils.isClickedOutside(event, chatWindowElement)) {
|
||||||
|
handleFormBlur.blur();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function closeChat() {
|
function closeChat() {
|
||||||
chatVisibilityStore.set(false);
|
chatVisibilityStore.set(false);
|
||||||
}
|
}
|
||||||
@ -26,10 +35,10 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window on:keydown={onKeyDown}/>
|
<svelte:window on:keydown={onKeyDown} on:click={onClick}/>
|
||||||
|
|
||||||
|
|
||||||
<aside class="chatWindow" transition:fly="{{ x: -1000, duration: 500 }}">
|
<aside class="chatWindow" transition:fly="{{ x: -1000, duration: 500 }}" bind:this={chatWindowElement}>
|
||||||
<p class="close-icon" on:click={closeChat}>×</p>
|
<p class="close-icon" on:click={closeChat}>×</p>
|
||||||
<section class="messagesList" bind:this={listDom}>
|
<section class="messagesList" bind:this={listDom}>
|
||||||
<ul>
|
<ul>
|
||||||
@ -40,7 +49,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
<section class="messageForm">
|
<section class="messageForm">
|
||||||
<ChatMessageForm></ChatMessageForm>
|
<ChatMessageForm bind:handleForm={handleFormBlur}></ChatMessageForm>
|
||||||
</section>
|
</section>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
|
@ -7,13 +7,14 @@
|
|||||||
|
|
||||||
export let message: ChatMessage;
|
export let message: ChatMessage;
|
||||||
export let line: number;
|
export let line: number;
|
||||||
|
const chatStyleLink = "color: white; text-decoration: underline;";
|
||||||
|
|
||||||
$: author = message.author as PlayerInterface;
|
$: author = message.author as PlayerInterface;
|
||||||
$: targets = message.targets || [];
|
$: targets = message.targets || [];
|
||||||
$: texts = message.text || [];
|
$: texts = message.text || [];
|
||||||
|
|
||||||
function urlifyText(text: string): string {
|
function urlifyText(text: string): string {
|
||||||
return HtmlUtils.urlify(text)
|
return HtmlUtils.urlify(text, chatStyleLink);
|
||||||
}
|
}
|
||||||
function renderDate(date: Date) {
|
function renderDate(date: Date) {
|
||||||
return date.toLocaleTimeString(navigator.language, {
|
return date.toLocaleTimeString(navigator.language, {
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {chatMessagesStore, chatInputFocusStore} from "../../Stores/ChatStore";
|
import {chatMessagesStore, chatInputFocusStore} from "../../Stores/ChatStore";
|
||||||
|
|
||||||
|
export const handleForm = {
|
||||||
|
blur() {
|
||||||
|
inputElement.blur();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let inputElement: HTMLElement;
|
||||||
let newMessageText = '';
|
let newMessageText = '';
|
||||||
|
|
||||||
function onFocus() {
|
function onFocus() {
|
||||||
@ -18,7 +24,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<form on:submit|preventDefault={saveMessage}>
|
<form on:submit|preventDefault={saveMessage}>
|
||||||
<input type="text" bind:value={newMessageText} placeholder="Enter your message..." on:focus={onFocus} on:blur={onBlur} >
|
<input type="text" bind:value={newMessageText} placeholder="Enter your message..." on:focus={onFocus} on:blur={onBlur} bind:this={inputElement}>
|
||||||
<button type="submit">
|
<button type="submit">
|
||||||
<img src="/static/images/send.png" alt="Send" width="20">
|
<img src="/static/images/send.png" alt="Send" width="20">
|
||||||
</button>
|
</button>
|
||||||
|
@ -6,6 +6,7 @@ import { GameConnexionTypes, urlManager } from "../Url/UrlManager";
|
|||||||
import { localUserStore } from "./LocalUserStore";
|
import { localUserStore } from "./LocalUserStore";
|
||||||
import { CharacterTexture, LocalUser } from "./LocalUser";
|
import { CharacterTexture, LocalUser } from "./LocalUser";
|
||||||
import { Room } from "./Room";
|
import { Room } from "./Room";
|
||||||
|
import { _ServiceWorker } from "../Network/ServiceWorker";
|
||||||
|
|
||||||
class ConnectionManager {
|
class ConnectionManager {
|
||||||
private localUser!: LocalUser;
|
private localUser!: LocalUser;
|
||||||
@ -14,6 +15,8 @@ class ConnectionManager {
|
|||||||
private reconnectingTimeout: NodeJS.Timeout | null = null;
|
private reconnectingTimeout: NodeJS.Timeout | null = null;
|
||||||
private _unloading: boolean = false;
|
private _unloading: boolean = false;
|
||||||
|
|
||||||
|
private serviceWorker?: _ServiceWorker;
|
||||||
|
|
||||||
get unloading() {
|
get unloading() {
|
||||||
return this._unloading;
|
return this._unloading;
|
||||||
}
|
}
|
||||||
@ -30,6 +33,8 @@ class ConnectionManager {
|
|||||||
public async initGameConnexion(): Promise<Room> {
|
public async initGameConnexion(): Promise<Room> {
|
||||||
const connexionType = urlManager.getGameConnexionType();
|
const connexionType = urlManager.getGameConnexionType();
|
||||||
this.connexionType = connexionType;
|
this.connexionType = connexionType;
|
||||||
|
|
||||||
|
let room: Room | null = null;
|
||||||
if (connexionType === GameConnexionTypes.register) {
|
if (connexionType === GameConnexionTypes.register) {
|
||||||
const organizationMemberToken = urlManager.getOrganizationToken();
|
const organizationMemberToken = urlManager.getOrganizationToken();
|
||||||
const data = await Axios.post(`${PUSHER_URL}/register`, { organizationMemberToken }).then(
|
const data = await Axios.post(`${PUSHER_URL}/register`, { organizationMemberToken }).then(
|
||||||
@ -40,7 +45,7 @@ class ConnectionManager {
|
|||||||
|
|
||||||
const roomUrl = data.roomUrl;
|
const roomUrl = data.roomUrl;
|
||||||
|
|
||||||
const room = await Room.createRoom(
|
room = await Room.createRoom(
|
||||||
new URL(
|
new URL(
|
||||||
window.location.protocol +
|
window.location.protocol +
|
||||||
"//" +
|
"//" +
|
||||||
@ -51,7 +56,6 @@ class ConnectionManager {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
urlManager.pushRoomIdToUrl(room);
|
urlManager.pushRoomIdToUrl(room);
|
||||||
return Promise.resolve(room);
|
|
||||||
} else if (
|
} else if (
|
||||||
connexionType === GameConnexionTypes.organization ||
|
connexionType === GameConnexionTypes.organization ||
|
||||||
connexionType === GameConnexionTypes.anonymous ||
|
connexionType === GameConnexionTypes.anonymous ||
|
||||||
@ -90,7 +94,7 @@ class ConnectionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//get detail map for anonymous login and set texture in local storage
|
//get detail map for anonymous login and set texture in local storage
|
||||||
const room = await Room.createRoom(new URL(roomPath));
|
room = await Room.createRoom(new URL(roomPath));
|
||||||
if (room.textures != undefined && room.textures.length > 0) {
|
if (room.textures != undefined && room.textures.length > 0) {
|
||||||
//check if texture was changed
|
//check if texture was changed
|
||||||
if (localUser.textures.length === 0) {
|
if (localUser.textures.length === 0) {
|
||||||
@ -107,10 +111,13 @@ class ConnectionManager {
|
|||||||
this.localUser = localUser;
|
this.localUser = localUser;
|
||||||
localUserStore.saveUser(localUser);
|
localUserStore.saveUser(localUser);
|
||||||
}
|
}
|
||||||
return Promise.resolve(room);
|
}
|
||||||
|
if (room == undefined) {
|
||||||
|
return Promise.reject(new Error("Invalid URL"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject(new Error("Invalid URL"));
|
this.serviceWorker = new _ServiceWorker();
|
||||||
|
return Promise.resolve(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async verifyToken(token: string): Promise<void> {
|
private async verifyToken(token: string): Promise<void> {
|
||||||
@ -148,6 +155,7 @@ class ConnectionManager {
|
|||||||
viewport,
|
viewport,
|
||||||
companion
|
companion
|
||||||
);
|
);
|
||||||
|
|
||||||
connection.onConnectError((error: object) => {
|
connection.onConnectError((error: object) => {
|
||||||
console.log("An error occurred while connecting to socket server. Retrying");
|
console.log("An error occurred while connecting to socket server. Retrying");
|
||||||
reject(error);
|
reject(error);
|
||||||
@ -166,6 +174,9 @@ class ConnectionManager {
|
|||||||
});
|
});
|
||||||
|
|
||||||
connection.onConnect((connect: OnConnectInterface) => {
|
connection.onConnect((connect: OnConnectInterface) => {
|
||||||
|
//save last room url connected
|
||||||
|
localUserStore.setLastRoomUrl(roomUrl);
|
||||||
|
|
||||||
resolve(connect);
|
resolve(connect);
|
||||||
});
|
});
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
|
@ -1,60 +1,61 @@
|
|||||||
import {areCharacterLayersValid, isUserNameValid, LocalUser} from "./LocalUser";
|
import { areCharacterLayersValid, isUserNameValid, LocalUser } from "./LocalUser";
|
||||||
|
|
||||||
const playerNameKey = 'playerName';
|
const playerNameKey = "playerName";
|
||||||
const selectedPlayerKey = 'selectedPlayer';
|
const selectedPlayerKey = "selectedPlayer";
|
||||||
const customCursorPositionKey = 'customCursorPosition';
|
const customCursorPositionKey = "customCursorPosition";
|
||||||
const characterLayersKey = 'characterLayers';
|
const characterLayersKey = "characterLayers";
|
||||||
const companionKey = 'companion';
|
const companionKey = "companion";
|
||||||
const gameQualityKey = 'gameQuality';
|
const gameQualityKey = "gameQuality";
|
||||||
const videoQualityKey = 'videoQuality';
|
const videoQualityKey = "videoQuality";
|
||||||
const audioPlayerVolumeKey = 'audioVolume';
|
const audioPlayerVolumeKey = "audioVolume";
|
||||||
const audioPlayerMuteKey = 'audioMute';
|
const audioPlayerMuteKey = "audioMute";
|
||||||
const helpCameraSettingsShown = 'helpCameraSettingsShown';
|
const helpCameraSettingsShown = "helpCameraSettingsShown";
|
||||||
const fullscreenKey = 'fullscreen';
|
const fullscreenKey = "fullscreen";
|
||||||
|
const lastRoomUrl = "lastRoomUrl";
|
||||||
|
|
||||||
class LocalUserStore {
|
class LocalUserStore {
|
||||||
saveUser(localUser: LocalUser) {
|
saveUser(localUser: LocalUser) {
|
||||||
localStorage.setItem('localUser', JSON.stringify(localUser));
|
localStorage.setItem("localUser", JSON.stringify(localUser));
|
||||||
}
|
}
|
||||||
getLocalUser(): LocalUser|null {
|
getLocalUser(): LocalUser | null {
|
||||||
const data = localStorage.getItem('localUser');
|
const data = localStorage.getItem("localUser");
|
||||||
return data ? JSON.parse(data) : null;
|
return data ? JSON.parse(data) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
setName(name:string): void {
|
setName(name: string): void {
|
||||||
localStorage.setItem(playerNameKey, name);
|
localStorage.setItem(playerNameKey, name);
|
||||||
}
|
}
|
||||||
getName(): string|null {
|
getName(): string | null {
|
||||||
const value = localStorage.getItem(playerNameKey) || '';
|
const value = localStorage.getItem(playerNameKey) || "";
|
||||||
return isUserNameValid(value) ? value : null;
|
return isUserNameValid(value) ? value : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
setPlayerCharacterIndex(playerCharacterIndex: number): void {
|
setPlayerCharacterIndex(playerCharacterIndex: number): void {
|
||||||
localStorage.setItem(selectedPlayerKey, ''+playerCharacterIndex);
|
localStorage.setItem(selectedPlayerKey, "" + playerCharacterIndex);
|
||||||
}
|
}
|
||||||
getPlayerCharacterIndex(): number {
|
getPlayerCharacterIndex(): number {
|
||||||
return parseInt(localStorage.getItem(selectedPlayerKey) || '');
|
return parseInt(localStorage.getItem(selectedPlayerKey) || "");
|
||||||
}
|
}
|
||||||
|
|
||||||
setCustomCursorPosition(activeRow:number, selectedLayers: number[]): void {
|
setCustomCursorPosition(activeRow: number, selectedLayers: number[]): void {
|
||||||
localStorage.setItem(customCursorPositionKey, 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(localStorage.getItem(customCursorPositionKey) || "null");
|
return JSON.parse(localStorage.getItem(customCursorPositionKey) || "null");
|
||||||
}
|
}
|
||||||
|
|
||||||
setCharacterLayers(layers: string[]): void {
|
setCharacterLayers(layers: string[]): void {
|
||||||
localStorage.setItem(characterLayersKey, JSON.stringify(layers));
|
localStorage.setItem(characterLayersKey, JSON.stringify(layers));
|
||||||
}
|
}
|
||||||
getCharacterLayers(): string[]|null {
|
getCharacterLayers(): string[] | null {
|
||||||
const value = JSON.parse(localStorage.getItem(characterLayersKey) || "null");
|
const value = JSON.parse(localStorage.getItem(characterLayersKey) || "null");
|
||||||
return areCharacterLayersValid(value) ? value : null;
|
return areCharacterLayersValid(value) ? value : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCompanion(companion: string|null): void {
|
setCompanion(companion: string | null): void {
|
||||||
return localStorage.setItem(companionKey, JSON.stringify(companion));
|
return localStorage.setItem(companionKey, JSON.stringify(companion));
|
||||||
}
|
}
|
||||||
getCompanion(): string|null {
|
getCompanion(): string | null {
|
||||||
const companion = JSON.parse(localStorage.getItem(companionKey) || "null");
|
const companion = JSON.parse(localStorage.getItem(companionKey) || "null");
|
||||||
|
|
||||||
if (typeof companion !== "string" || companion === "") {
|
if (typeof companion !== "string" || companion === "") {
|
||||||
@ -68,45 +69,52 @@ class LocalUserStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setGameQualityValue(value: number): void {
|
setGameQualityValue(value: number): void {
|
||||||
localStorage.setItem(gameQualityKey, '' + value);
|
localStorage.setItem(gameQualityKey, "" + value);
|
||||||
}
|
}
|
||||||
getGameQualityValue(): number {
|
getGameQualityValue(): number {
|
||||||
return parseInt(localStorage.getItem(gameQualityKey) || '60');
|
return parseInt(localStorage.getItem(gameQualityKey) || "60");
|
||||||
}
|
}
|
||||||
|
|
||||||
setVideoQualityValue(value: number): void {
|
setVideoQualityValue(value: number): void {
|
||||||
localStorage.setItem(videoQualityKey, '' + value);
|
localStorage.setItem(videoQualityKey, "" + value);
|
||||||
}
|
}
|
||||||
getVideoQualityValue(): number {
|
getVideoQualityValue(): number {
|
||||||
return parseInt(localStorage.getItem(videoQualityKey) || '20');
|
return parseInt(localStorage.getItem(videoQualityKey) || "20");
|
||||||
}
|
}
|
||||||
|
|
||||||
setAudioPlayerVolume(value: number): void {
|
setAudioPlayerVolume(value: number): void {
|
||||||
localStorage.setItem(audioPlayerVolumeKey, '' + value);
|
localStorage.setItem(audioPlayerVolumeKey, "" + value);
|
||||||
}
|
}
|
||||||
getAudioPlayerVolume(): number {
|
getAudioPlayerVolume(): number {
|
||||||
return parseFloat(localStorage.getItem(audioPlayerVolumeKey) || '1');
|
return parseFloat(localStorage.getItem(audioPlayerVolumeKey) || "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
setAudioPlayerMuted(value: boolean): void {
|
setAudioPlayerMuted(value: boolean): void {
|
||||||
localStorage.setItem(audioPlayerMuteKey, value.toString());
|
localStorage.setItem(audioPlayerMuteKey, value.toString());
|
||||||
}
|
}
|
||||||
getAudioPlayerMuted(): boolean {
|
getAudioPlayerMuted(): boolean {
|
||||||
return localStorage.getItem(audioPlayerMuteKey) === 'true';
|
return localStorage.getItem(audioPlayerMuteKey) === "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
setHelpCameraSettingsShown(): void {
|
setHelpCameraSettingsShown(): void {
|
||||||
localStorage.setItem(helpCameraSettingsShown, '1');
|
localStorage.setItem(helpCameraSettingsShown, "1");
|
||||||
}
|
}
|
||||||
getHelpCameraSettingsShown(): boolean {
|
getHelpCameraSettingsShown(): boolean {
|
||||||
return localStorage.getItem(helpCameraSettingsShown) === '1';
|
return localStorage.getItem(helpCameraSettingsShown) === "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
setFullscreen(value: boolean): void {
|
setFullscreen(value: boolean): void {
|
||||||
localStorage.setItem(fullscreenKey, value.toString());
|
localStorage.setItem(fullscreenKey, value.toString());
|
||||||
}
|
}
|
||||||
getFullscreen(): boolean {
|
getFullscreen(): boolean {
|
||||||
return localStorage.getItem(fullscreenKey) === 'true';
|
return localStorage.getItem(fullscreenKey) === "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
setLastRoomUrl(roomUrl: string): void {
|
||||||
|
localStorage.setItem(lastRoomUrl, roomUrl.toString());
|
||||||
|
}
|
||||||
|
getLastRoomUrl(): string {
|
||||||
|
return localStorage.getItem(lastRoomUrl) ?? "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
front/src/Network/ServiceWorker.ts
Normal file
20
front/src/Network/ServiceWorker.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
export class _ServiceWorker {
|
||||||
|
constructor() {
|
||||||
|
if ("serviceWorker" in navigator) {
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
window.addEventListener("load", () => {
|
||||||
|
navigator.serviceWorker
|
||||||
|
.register("/resources/service-worker.js")
|
||||||
|
.then((serviceWorker) => {
|
||||||
|
console.info("Service Worker registered: ", serviceWorker);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error registering the Service Worker: ", error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,35 +1,43 @@
|
|||||||
import type {ITiledMapObject} from "../Map/ITiledMap";
|
import type { ITiledMapObject } from "../Map/ITiledMap";
|
||||||
import type {GameScene} from "../Game/GameScene";
|
import type { GameScene } from "../Game/GameScene";
|
||||||
|
import { type } from "os";
|
||||||
|
|
||||||
export class TextUtils {
|
export class TextUtils {
|
||||||
public static createTextFromITiledMapObject(scene: GameScene, object: ITiledMapObject): void {
|
public static createTextFromITiledMapObject(scene: GameScene, object: ITiledMapObject): void {
|
||||||
if (object.text === undefined) {
|
if (object.text === undefined) {
|
||||||
throw new Error('This object has not textual representation.');
|
throw new Error("This object has not textual representation.");
|
||||||
}
|
}
|
||||||
const options: {
|
const options: {
|
||||||
fontStyle?: string,
|
fontStyle?: string;
|
||||||
fontSize?: string,
|
fontSize?: string;
|
||||||
fontFamily?: string,
|
fontFamily?: string;
|
||||||
color?: string,
|
color?: string;
|
||||||
align?: string,
|
align?: string;
|
||||||
wordWrap?: {
|
wordWrap?: {
|
||||||
width: number,
|
width: number;
|
||||||
useAdvancedWrap?: boolean
|
useAdvancedWrap?: boolean;
|
||||||
}
|
};
|
||||||
} = {};
|
} = {};
|
||||||
if (object.text.italic) {
|
if (object.text.italic) {
|
||||||
options.fontStyle = 'italic';
|
options.fontStyle = "italic";
|
||||||
}
|
}
|
||||||
// Note: there is no support for "strikeout" and "underline"
|
// Note: there is no support for "strikeout" and "underline"
|
||||||
let fontSize: number = 16;
|
let fontSize: number = 16;
|
||||||
if (object.text.pixelsize) {
|
if (object.text.pixelsize) {
|
||||||
fontSize = object.text.pixelsize;
|
fontSize = object.text.pixelsize;
|
||||||
}
|
}
|
||||||
options.fontSize = fontSize + 'px';
|
options.fontSize = fontSize + "px";
|
||||||
if (object.text.fontfamily) {
|
if (object.text.fontfamily) {
|
||||||
options.fontFamily = '"'+object.text.fontfamily+'"';
|
options.fontFamily = '"' + object.text.fontfamily + '"';
|
||||||
}
|
}
|
||||||
let color = '#000000';
|
if (object.properties !== undefined) {
|
||||||
|
for (const property of object.properties) {
|
||||||
|
if (property.name === "font-family" && typeof property.value === "string") {
|
||||||
|
options.fontFamily = property.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let color = "#000000";
|
||||||
if (object.text.color !== undefined) {
|
if (object.text.color !== undefined) {
|
||||||
color = object.text.color;
|
color = object.text.color;
|
||||||
}
|
}
|
||||||
@ -38,7 +46,7 @@ export class TextUtils {
|
|||||||
options.wordWrap = {
|
options.wordWrap = {
|
||||||
width: object.width,
|
width: object.width,
|
||||||
//useAdvancedWrap: true
|
//useAdvancedWrap: true
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
if (object.text.halign !== undefined) {
|
if (object.text.halign !== undefined) {
|
||||||
options.align = object.text.halign;
|
options.align = object.text.halign;
|
||||||
|
@ -107,7 +107,7 @@ export const createLoadingPromise = (
|
|||||||
loadPlugin.spritesheet(playerResourceDescriptor.name, playerResourceDescriptor.img, frameConfig);
|
loadPlugin.spritesheet(playerResourceDescriptor.name, playerResourceDescriptor.img, frameConfig);
|
||||||
const errorCallback = (file: { src: string }) => {
|
const errorCallback = (file: { src: string }) => {
|
||||||
if (file.src !== playerResourceDescriptor.img) return;
|
if (file.src !== playerResourceDescriptor.img) return;
|
||||||
console.error("failed loading player ressource: ", playerResourceDescriptor);
|
console.error("failed loading player resource: ", playerResourceDescriptor);
|
||||||
rej(playerResourceDescriptor);
|
rej(playerResourceDescriptor);
|
||||||
loadPlugin.off("filecomplete-spritesheet-" + playerResourceDescriptor.name, successCallback);
|
loadPlugin.off("filecomplete-spritesheet-" + playerResourceDescriptor.name, successCallback);
|
||||||
loadPlugin.off("loaderror", errorCallback);
|
loadPlugin.off("loaderror", errorCallback);
|
||||||
|
@ -192,7 +192,7 @@ export class GameScene extends DirtyScene {
|
|||||||
private popUpElements: Map<number, DOMElement> = new Map<number, Phaser.GameObjects.DOMElement>();
|
private popUpElements: Map<number, DOMElement> = new Map<number, Phaser.GameObjects.DOMElement>();
|
||||||
private originalMapUrl: string | undefined;
|
private originalMapUrl: string | undefined;
|
||||||
private pinchManager: PinchManager | undefined;
|
private pinchManager: PinchManager | undefined;
|
||||||
private mapTransitioning: boolean = false; //used to prevent transitions happenning at the same time.
|
private mapTransitioning: boolean = false; //used to prevent transitions happening at the same time.
|
||||||
private emoteManager!: EmoteManager;
|
private emoteManager!: EmoteManager;
|
||||||
private preloading: boolean = true;
|
private preloading: boolean = true;
|
||||||
private startPositionCalculator!: StartPositionCalculator;
|
private startPositionCalculator!: StartPositionCalculator;
|
||||||
@ -434,7 +434,7 @@ export class GameScene extends DirtyScene {
|
|||||||
this.characterLayers = gameManager.getCharacterLayers();
|
this.characterLayers = gameManager.getCharacterLayers();
|
||||||
this.companion = gameManager.getCompanion();
|
this.companion = gameManager.getCompanion();
|
||||||
|
|
||||||
//initalise map
|
//initialise map
|
||||||
this.Map = this.add.tilemap(this.MapUrlFile);
|
this.Map = this.add.tilemap(this.MapUrlFile);
|
||||||
const mapDirUrl = this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf("/"));
|
const mapDirUrl = this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf("/"));
|
||||||
this.mapFile.tilesets.forEach((tileset: ITiledTileSet) => {
|
this.mapFile.tilesets.forEach((tileset: ITiledTileSet) => {
|
||||||
|
@ -45,7 +45,7 @@ export class StartPositionCalculator {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param selectedLayer this is always the layer that is selected with the hash in the url
|
* @param selectedLayer this is always the layer that is selected with the hash in the url
|
||||||
* @param selectedOrDefaultLayer this can also be the {defaultStartLayerName} if the {selectedLayer} didnt yield any start points
|
* @param selectedOrDefaultLayer this can also be the {defaultStartLayerName} if the {selectedLayer} did not yield any start points
|
||||||
*/
|
*/
|
||||||
public initPositionFromLayerName(selectedOrDefaultLayer: string | null, selectedLayer: string | null) {
|
public initPositionFromLayerName(selectedOrDefaultLayer: string | null, selectedLayer: string | null) {
|
||||||
if (!selectedOrDefaultLayer) {
|
if (!selectedOrDefaultLayer) {
|
||||||
@ -73,7 +73,7 @@ export class StartPositionCalculator {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param selectedLayer this is always the layer that is selected with the hash in the url
|
* @param selectedLayer this is always the layer that is selected with the hash in the url
|
||||||
* @param selectedOrDefaultLayer this can also be the default layer if the {selectedLayer} didnt yield any start points
|
* @param selectedOrDefaultLayer this can also be the default layer if the {selectedLayer} did not yield any start points
|
||||||
*/
|
*/
|
||||||
private startUser(selectedOrDefaultLayer: ITiledMapTileLayer, selectedLayer: string | null): PositionInterface {
|
private startUser(selectedOrDefaultLayer: ITiledMapTileLayer, selectedLayer: string | null): PositionInterface {
|
||||||
const tiles = selectedOrDefaultLayer.data;
|
const tiles = selectedOrDefaultLayer.data;
|
||||||
|
@ -244,6 +244,7 @@ export class CustomizeScene extends AbstractCharacterScene {
|
|||||||
update(time: number, delta: number): void {
|
update(time: number, delta: number): void {
|
||||||
if (this.lazyloadingAttempt) {
|
if (this.lazyloadingAttempt) {
|
||||||
this.moveLayers();
|
this.moveLayers();
|
||||||
|
this.doMoveCursorHorizontally(this.moveHorizontally);
|
||||||
this.lazyloadingAttempt = false;
|
this.lazyloadingAttempt = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import type { Direction } from "../../types";
|
import type { Direction } from "../../types";
|
||||||
import type {GameScene} from "../Game/GameScene";
|
import type { GameScene } from "../Game/GameScene";
|
||||||
import {touchScreenManager} from "../../Touch/TouchScreenManager";
|
import { touchScreenManager } from "../../Touch/TouchScreenManager";
|
||||||
import {MobileJoystick} from "../Components/MobileJoystick";
|
import { MobileJoystick } from "../Components/MobileJoystick";
|
||||||
import {enableUserInputsStore} from "../../Stores/UserInputStore";
|
import { enableUserInputsStore } from "../../Stores/UserInputStore";
|
||||||
|
|
||||||
interface UserInputManagerDatum {
|
interface UserInputManagerDatum {
|
||||||
keyInstance: Phaser.Input.Keyboard.Key;
|
keyInstance: Phaser.Input.Keyboard.Key;
|
||||||
event: UserInputEvent
|
event: UserInputEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum UserInputEvent {
|
export enum UserInputEvent {
|
||||||
@ -20,10 +20,9 @@ export enum UserInputEvent {
|
|||||||
JoystickMove,
|
JoystickMove,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//we cannot use a map structure so we have to create a replacement
|
||||||
//we cannot use a map structure so we have to create a replacment
|
|
||||||
export class ActiveEventList {
|
export class ActiveEventList {
|
||||||
private eventMap : Map<UserInputEvent, boolean> = new Map<UserInputEvent, boolean>();
|
private eventMap: Map<UserInputEvent, boolean> = new Map<UserInputEvent, boolean>();
|
||||||
|
|
||||||
get(event: UserInputEvent): boolean {
|
get(event: UserInputEvent): boolean {
|
||||||
return this.eventMap.get(event) || false;
|
return this.eventMap.get(event) || false;
|
||||||
@ -43,7 +42,7 @@ export class ActiveEventList {
|
|||||||
export class UserInputManager {
|
export class UserInputManager {
|
||||||
private KeysCode!: UserInputManagerDatum[];
|
private KeysCode!: UserInputManagerDatum[];
|
||||||
private Scene: GameScene;
|
private Scene: GameScene;
|
||||||
private isInputDisabled : boolean;
|
private isInputDisabled: boolean;
|
||||||
|
|
||||||
private joystick!: MobileJoystick;
|
private joystick!: MobileJoystick;
|
||||||
private joystickEvents = new ActiveEventList();
|
private joystickEvents = new ActiveEventList();
|
||||||
@ -61,8 +60,8 @@ export class UserInputManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enableUserInputsStore.subscribe((enable) => {
|
enableUserInputsStore.subscribe((enable) => {
|
||||||
enable ? this.restoreControls() : this.disableControls()
|
enable ? this.restoreControls() : this.disableControls();
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
initVirtualJoystick() {
|
initVirtualJoystick() {
|
||||||
@ -91,39 +90,81 @@ export class UserInputManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
initKeyBoardEvent(){
|
initKeyBoardEvent() {
|
||||||
this.KeysCode = [
|
this.KeysCode = [
|
||||||
{event: UserInputEvent.MoveUp, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Z, false) },
|
{
|
||||||
{event: UserInputEvent.MoveUp, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W, false) },
|
event: UserInputEvent.MoveUp,
|
||||||
{event: UserInputEvent.MoveLeft, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q, false) },
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Z, false),
|
||||||
{event: UserInputEvent.MoveLeft, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A, false) },
|
},
|
||||||
{event: UserInputEvent.MoveDown, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S, false) },
|
{
|
||||||
{event: UserInputEvent.MoveRight, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D, false) },
|
event: UserInputEvent.MoveUp,
|
||||||
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W, false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: UserInputEvent.MoveLeft,
|
||||||
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q, false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: UserInputEvent.MoveLeft,
|
||||||
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A, false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: UserInputEvent.MoveDown,
|
||||||
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S, false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: UserInputEvent.MoveRight,
|
||||||
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D, false),
|
||||||
|
},
|
||||||
|
|
||||||
{event: UserInputEvent.MoveUp, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.UP, false) },
|
{
|
||||||
{event: UserInputEvent.MoveLeft, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.LEFT, false) },
|
event: UserInputEvent.MoveUp,
|
||||||
{event: UserInputEvent.MoveDown, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.DOWN, false) },
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.UP, false),
|
||||||
{event: UserInputEvent.MoveRight, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.RIGHT, false) },
|
},
|
||||||
|
{
|
||||||
|
event: UserInputEvent.MoveLeft,
|
||||||
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.LEFT, false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: UserInputEvent.MoveDown,
|
||||||
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.DOWN, false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: UserInputEvent.MoveRight,
|
||||||
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.RIGHT, false),
|
||||||
|
},
|
||||||
|
|
||||||
{event: UserInputEvent.SpeedUp, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SHIFT, false) },
|
{
|
||||||
|
event: UserInputEvent.SpeedUp,
|
||||||
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SHIFT, false),
|
||||||
|
},
|
||||||
|
|
||||||
{event: UserInputEvent.Interact, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E, false) },
|
{
|
||||||
{event: UserInputEvent.Interact, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE, false) },
|
event: UserInputEvent.Interact,
|
||||||
{event: UserInputEvent.Shout, keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.F, false) },
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E, false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: UserInputEvent.Interact,
|
||||||
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE, false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
event: UserInputEvent.Shout,
|
||||||
|
keyInstance: this.Scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.F, false),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
clearAllListeners(){
|
clearAllListeners() {
|
||||||
this.Scene.input.keyboard.removeAllListeners();
|
this.Scene.input.keyboard.removeAllListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo: should we also disable the joystick?
|
//todo: should we also disable the joystick?
|
||||||
disableControls(){
|
disableControls() {
|
||||||
this.Scene.input.keyboard.removeAllKeys();
|
this.Scene.input.keyboard.removeAllKeys();
|
||||||
this.isInputDisabled = true;
|
this.isInputDisabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreControls(){
|
restoreControls() {
|
||||||
this.initKeyBoardEvent();
|
this.initKeyBoardEvent();
|
||||||
this.isInputDisabled = false;
|
this.isInputDisabled = false;
|
||||||
}
|
}
|
||||||
@ -135,27 +176,27 @@ export class UserInputManager {
|
|||||||
this.joystickEvents.forEach((value, key) => {
|
this.joystickEvents.forEach((value, key) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case UserInputEvent.MoveUp:
|
case UserInputEvent.MoveUp:
|
||||||
case UserInputEvent.MoveDown:
|
case UserInputEvent.MoveDown:
|
||||||
this.joystickForceAccuY += this.joystick.forceY;
|
this.joystickForceAccuY += this.joystick.forceY;
|
||||||
if (Math.abs(this.joystickForceAccuY) > this.joystickForceThreshold) {
|
if (Math.abs(this.joystickForceAccuY) > this.joystickForceThreshold) {
|
||||||
eventsMap.set(key, value);
|
eventsMap.set(key, value);
|
||||||
this.joystickForceAccuY = 0;
|
this.joystickForceAccuY = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UserInputEvent.MoveLeft:
|
case UserInputEvent.MoveLeft:
|
||||||
case UserInputEvent.MoveRight:
|
case UserInputEvent.MoveRight:
|
||||||
this.joystickForceAccuX += this.joystick.forceX;
|
this.joystickForceAccuX += this.joystick.forceX;
|
||||||
if (Math.abs(this.joystickForceAccuX) > this.joystickForceThreshold) {
|
if (Math.abs(this.joystickForceAccuX) > this.joystickForceThreshold) {
|
||||||
eventsMap.set(key, value);
|
eventsMap.set(key, value);
|
||||||
this.joystickForceAccuX = 0;
|
this.joystickForceAccuX = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
eventsMap.set(UserInputEvent.JoystickMove, this.joystickEvents.any());
|
eventsMap.set(UserInputEvent.JoystickMove, this.joystickEvents.any());
|
||||||
this.KeysCode.forEach(d => {
|
this.KeysCode.forEach((d) => {
|
||||||
if (d.keyInstance.isDown) {
|
if (d.keyInstance.isDown) {
|
||||||
eventsMap.set(d.event, true);
|
eventsMap.set(d.event, true);
|
||||||
}
|
}
|
||||||
@ -163,18 +204,18 @@ export class UserInputManager {
|
|||||||
return eventsMap;
|
return eventsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
spaceEvent(callback : Function){
|
spaceEvent(callback: Function) {
|
||||||
this.Scene.input.keyboard.on('keyup-SPACE', (event: Event) => {
|
this.Scene.input.keyboard.on("keyup-SPACE", (event: Event) => {
|
||||||
callback();
|
callback();
|
||||||
return event;
|
return event;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addSpaceEventListner(callback : Function){
|
addSpaceEventListner(callback: Function) {
|
||||||
this.Scene.input.keyboard.addListener('keyup-SPACE', callback);
|
this.Scene.input.keyboard.addListener("keyup-SPACE", callback);
|
||||||
}
|
}
|
||||||
removeSpaceEventListner(callback : Function){
|
removeSpaceEventListner(callback: Function) {
|
||||||
this.Scene.input.keyboard.removeListener('keyup-SPACE', callback);
|
this.Scene.input.keyboard.removeListener("keyup-SPACE", callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy(): void {
|
destroy(): void {
|
||||||
@ -182,8 +223,11 @@ export class UserInputManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private initMouseWheel() {
|
private initMouseWheel() {
|
||||||
this.Scene.input.on('wheel', (pointer: unknown, gameObjects: unknown, deltaX: number, deltaY: number, deltaZ: number) => {
|
this.Scene.input.on(
|
||||||
this.Scene.zoomByFactor(1 - deltaY / 53 * 0.1);
|
"wheel",
|
||||||
});
|
(pointer: unknown, gameObjects: unknown, deltaX: number, deltaY: number, deltaZ: number) => {
|
||||||
|
this.Scene.zoomByFactor(1 - (deltaY / 53) * 0.1);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,12 +274,12 @@ export const mediaStreamConstraintsStore = derived(
|
|||||||
currentAudioConstraint = false;
|
currentAudioConstraint = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable webcam for privacy reasons (the game is not visible and we were talking to noone)
|
// Disable webcam for privacy reasons (the game is not visible and we were talking to no one)
|
||||||
if ($privacyShutdownStore === true) {
|
if ($privacyShutdownStore === true) {
|
||||||
currentVideoConstraint = false;
|
currentVideoConstraint = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable webcam for energy reasons (the user is not moving and we are talking to noone)
|
// Disable webcam for energy reasons (the user is not moving and we are talking to no one)
|
||||||
if ($cameraEnergySavingStore === true) {
|
if ($cameraEnergySavingStore === true) {
|
||||||
currentVideoConstraint = false;
|
currentVideoConstraint = false;
|
||||||
currentAudioConstraint = false;
|
currentAudioConstraint = false;
|
||||||
|
@ -31,7 +31,7 @@ export class HtmlUtils {
|
|||||||
return p.innerHTML;
|
return p.innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static urlify(text: string): string {
|
public static urlify(text: string, style: string = ""): string {
|
||||||
const urlRegex = /(https?:\/\/[^\s]+)/g;
|
const urlRegex = /(https?:\/\/[^\s]+)/g;
|
||||||
text = HtmlUtils.escapeHtml(text);
|
text = HtmlUtils.escapeHtml(text);
|
||||||
return text.replace(urlRegex, (url: string) => {
|
return text.replace(urlRegex, (url: string) => {
|
||||||
@ -40,10 +40,19 @@ export class HtmlUtils {
|
|||||||
link.target = "_blank";
|
link.target = "_blank";
|
||||||
const text = document.createTextNode(url);
|
const text = document.createTextNode(url);
|
||||||
link.appendChild(text);
|
link.appendChild(text);
|
||||||
|
link.setAttribute("style", style);
|
||||||
return link.outerHTML;
|
return link.outerHTML;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static isClickedInside(event: MouseEvent, target: HTMLElement): boolean {
|
||||||
|
return !!event.composedPath().find((et) => et === target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static isClickedOutside(event: MouseEvent, target: HTMLElement): boolean {
|
||||||
|
return !this.isClickedInside(event, target);
|
||||||
|
}
|
||||||
|
|
||||||
private static isHtmlElement<T extends HTMLElement>(elem: HTMLElement | null): elem is T {
|
private static isHtmlElement<T extends HTMLElement>(elem: HTMLElement | null): elem is T {
|
||||||
return elem !== null;
|
return elem !== null;
|
||||||
}
|
}
|
||||||
|
@ -295,7 +295,7 @@ export class SimplePeer {
|
|||||||
// I do understand the method closeConnection is called twice, but I don't understand how they manage to run in parallel.
|
// I do understand the method closeConnection is called twice, but I don't understand how they manage to run in parallel.
|
||||||
peer.destroy();
|
peer.destroy();
|
||||||
|
|
||||||
//Comment this peer connexion because if we delete and try to reshare screen, the RTCPeerConnection send renegociate event. This array will be remove when user left circle discussion
|
//Comment this peer connection because if we delete and try to reshare screen, the RTCPeerConnection send renegotiate event. This array will be remove when user left circle discussion
|
||||||
/*if(!this.PeerScreenSharingConnectionArray.delete(userId)){
|
/*if(!this.PeerScreenSharingConnectionArray.delete(userId)){
|
||||||
throw 'Couln\'t delete peer screen sharing connexion';
|
throw 'Couln\'t delete peer screen sharing connexion';
|
||||||
}*/
|
}*/
|
||||||
@ -370,14 +370,14 @@ export class SimplePeer {
|
|||||||
console.error(
|
console.error(
|
||||||
'Could not find peer whose ID is "' + data.userId + '" in receiveWebrtcScreenSharingSignal'
|
'Could not find peer whose ID is "' + data.userId + '" in receiveWebrtcScreenSharingSignal'
|
||||||
);
|
);
|
||||||
console.info("Attempt to create new peer connexion");
|
console.info("Attempt to create new peer connection");
|
||||||
if (stream) {
|
if (stream) {
|
||||||
this.sendLocalScreenSharingStreamToUser(data.userId, stream);
|
this.sendLocalScreenSharingStreamToUser(data.userId, stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`receiveWebrtcSignal => ${data.userId}`, e);
|
console.error(`receiveWebrtcSignal => ${data.userId}`, e);
|
||||||
//Comment this peer connexion because if we delete and try to reshare screen, the RTCPeerConnection send renegociate event. This array will be remove when user left circle discussion
|
//Comment this peer connection because if we delete and try to reshare screen, the RTCPeerConnection send renegotiate event. This array will be remove when user left circle discussion
|
||||||
//this.PeerScreenSharingConnectionArray.delete(data.userId);
|
//this.PeerScreenSharingConnectionArray.delete(data.userId);
|
||||||
this.receiveWebrtcScreenSharingSignal(data);
|
this.receiveWebrtcScreenSharingSignal(data);
|
||||||
}
|
}
|
||||||
@ -485,7 +485,7 @@ export class SimplePeer {
|
|||||||
|
|
||||||
if (!PeerConnectionScreenSharing.isReceivingScreenSharingStream()) {
|
if (!PeerConnectionScreenSharing.isReceivingScreenSharingStream()) {
|
||||||
PeerConnectionScreenSharing.destroy();
|
PeerConnectionScreenSharing.destroy();
|
||||||
//Comment this peer connexion because if we delete and try to reshare screen, the RTCPeerConnection send renegociate event. This array will be remove when user left circle discussion
|
//Comment this peer connection because if we delete and try to reshare screen, the RTCPeerConnection send renegotiate event. This array will be remove when user left circle discussion
|
||||||
//this.PeerScreenSharingConnectionArray.delete(userId);
|
//this.PeerScreenSharingConnectionArray.delete(userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,16 +162,3 @@ const app = new App({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|
||||||
if ("serviceWorker" in navigator) {
|
|
||||||
window.addEventListener("load", function () {
|
|
||||||
navigator.serviceWorker
|
|
||||||
.register("/resources/service-worker.js")
|
|
||||||
.then((serviceWorker) => {
|
|
||||||
console.log("Service Worker registered: ", serviceWorker);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error("Error registering the Service Worker: ", error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -1,28 +1,28 @@
|
|||||||
import "jasmine";
|
import "jasmine";
|
||||||
import {getRessourceDescriptor} from "../../../src/Phaser/Entity/PlayerTexturesLoadingManager";
|
import { getRessourceDescriptor } from "../../../src/Phaser/Entity/PlayerTexturesLoadingManager";
|
||||||
|
|
||||||
describe("getRessourceDescriptor()", () => {
|
describe("getRessourceDescriptor()", () => {
|
||||||
it(", if given a valid descriptor as parameter, should return it", () => {
|
it(", if given a valid descriptor as parameter, should return it", () => {
|
||||||
const desc = getRessourceDescriptor({name: 'name', img: 'url'});
|
const desc = getRessourceDescriptor({ name: "name", img: "url" });
|
||||||
expect(desc.name).toEqual('name');
|
expect(desc.name).toEqual("name");
|
||||||
expect(desc.img).toEqual('url');
|
expect(desc.img).toEqual("url");
|
||||||
});
|
});
|
||||||
|
|
||||||
it(", if given a string as parameter, should search trough hardcoded values", () => {
|
it(", if given a string as parameter, should search through hardcoded values", () => {
|
||||||
const desc = getRessourceDescriptor('male1');
|
const desc = getRessourceDescriptor("male1");
|
||||||
expect(desc.name).toEqual('male1');
|
expect(desc.name).toEqual("male1");
|
||||||
expect(desc.img).toEqual("resources/characters/pipoya/Male 01-1.png");
|
expect(desc.img).toEqual("resources/characters/pipoya/Male 01-1.png");
|
||||||
});
|
});
|
||||||
|
|
||||||
it(", if given a string as parameter, should search trough hardcoded values (bis)", () => {
|
it(", if given a string as parameter, should search through hardcoded values (bis)", () => {
|
||||||
const desc = getRessourceDescriptor('color_2');
|
const desc = getRessourceDescriptor("color_2");
|
||||||
expect(desc.name).toEqual('color_2');
|
expect(desc.name).toEqual("color_2");
|
||||||
expect(desc.img).toEqual("resources/customisation/character_color/character_color1.png");
|
expect(desc.img).toEqual("resources/customisation/character_color/character_color1.png");
|
||||||
});
|
});
|
||||||
|
|
||||||
it(", if given a descriptor without url as parameter, should search trough hardcoded values", () => {
|
it(", if given a descriptor without url as parameter, should search through hardcoded values", () => {
|
||||||
const desc = getRessourceDescriptor({name: 'male1', img: ''});
|
const desc = getRessourceDescriptor({ name: "male1", img: "" });
|
||||||
expect(desc.name).toEqual('male1');
|
expect(desc.name).toEqual("male1");
|
||||||
expect(desc.img).toEqual("resources/characters/pipoya/Male 01-1.png");
|
expect(desc.img).toEqual("resources/characters/pipoya/Male 01-1.png");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -176,7 +176,7 @@ Tuomo Untinen CC-BY-3.0
|
|||||||
|
|
||||||
Casper Nilsson
|
Casper Nilsson
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
- Asain themed shrine including red lantern
|
- Asian themed shrine including red lantern
|
||||||
- foodog statue
|
- foodog statue
|
||||||
- Toro
|
- Toro
|
||||||
- Cherry blossom tree
|
- Cherry blossom tree
|
||||||
|
@ -58,11 +58,17 @@
|
|||||||
"height":94.6489098314831,
|
"height":94.6489098314831,
|
||||||
"id":1,
|
"id":1,
|
||||||
"name":"",
|
"name":"",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"font-family",
|
||||||
|
"type":"string",
|
||||||
|
"value":"\"Press Start 2P\""
|
||||||
|
}],
|
||||||
"rotation":0,
|
"rotation":0,
|
||||||
"text":
|
"text":
|
||||||
{
|
{
|
||||||
"fontfamily":"Sans Serif",
|
"fontfamily":"Sans Serif",
|
||||||
"pixelsize":11,
|
"pixelsize":8,
|
||||||
"text":"Test:\nWalk on the carpet and press space\nResult:\nJitsi opens on meet.jit.si (check this in the network tab). Note: this test only makes sense if the default configured Jitsi instance is NOT meet.jit.si (check your .env file)",
|
"text":"Test:\nWalk on the carpet and press space\nResult:\nJitsi opens on meet.jit.si (check this in the network tab). Note: this test only makes sense if the default configured Jitsi instance is NOT meet.jit.si (check your .env file)",
|
||||||
"wrap":true
|
"wrap":true
|
||||||
},
|
},
|
||||||
|
@ -21,7 +21,7 @@ interface ZoneDescriptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PositionDispatcher {
|
export class PositionDispatcher {
|
||||||
// TODO: we need a way to clean the zones if noone is in the zone and noone listening (to free memory!)
|
// TODO: we need a way to clean the zones if no one is in the zone and no one listening (to free memory!)
|
||||||
|
|
||||||
private zones: Zone[][] = [];
|
private zones: Zone[][] = [];
|
||||||
|
|
||||||
|
@ -452,7 +452,7 @@ export class SocketManager implements ZoneEventListener {
|
|||||||
|
|
||||||
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("An error occured while generating the Jitsi JWT token: ", e);
|
console.error("An error occurred while generating the Jitsi JWT token: ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user