partey_workadventure/front/src/Connexion/RoomConnection.ts

946 lines
38 KiB
TypeScript
Raw Normal View History

import { PUSHER_URL, UPLOADER_URL } from "../Enum/EnvironmentVariable";
import Axios from "axios";
import type { UserSimplePeerInterface } from "../WebRtc/SimplePeer";
import { ProtobufClientUtils } from "../Network/ProtobufClientUtils";
import type {
GroupCreatedUpdatedMessageInterface,
2022-02-28 13:47:08 +01:00
GroupUsersUpdateMessageInterface,
MessageUserJoined,
PlayGlobalMessageInterface,
PositionInterface,
2020-09-25 18:29:22 +02:00
RoomJoinedMessageInterface,
ViewportInterface,
2020-09-25 18:29:22 +02:00
WebRtcSignalReceivedMessageInterface,
} from "./ConnexionModels";
import type { BodyResourceDescriptionInterface } from "../Phaser/Entity/PlayerTextures";
import { adminMessagesService } from "./AdminMessagesService";
import { connectionManager } from "./ConnectionManager";
import { get } from "svelte/store";
2022-02-23 14:40:19 +01:00
import { followRoleStore, followUsersStore } from "../Stores/FollowStore";
Refactoring Woka management (#1810) * Wrap websockets with HyperExpress * Add endpoints on pusher to resolve wokas * getting textures urls from pusher * Adding OpenAPI documentation for the pusher. The pusher now exposes a "/openapi" endpoint and a "/swagger-ui/" endpoint. * revert FRONT_URL * playerTextures metadata is being loaded via Phaser.Loader * fetch textures every time character or customize scene is open * Heavy changes: refactoring the pusher to always send the textures (and the front to accept them) * Sending character layer details to admin * Cleaning commented code * Fixing regex * Fix woka endpoints on pusher * Change error wording on pusher * Working on integration of the woka-list with the new admin endpoint. * Switching from "name" to "id" in texture object + using zod for woka/list validation * Add position on default woka data * Remove async on pusher option method * Fix woka list url * add options for /register * Fxiing loading the Woka list * Actually returning something in logout-callback * Copying messages to back too * remove customize button if no body parts are available (#1952) * remove customize button if no body parts are available * remove unused position field from PlayerTexturesCollection interface * removed unused label field * fix LocalUser test * little PlayerTextures class refactor * Fixing linting * Fixing missing Openapi packages in prod * Fixing back build Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: David Négrier <d.negrier@thecodingmachine.com> * Add returns on pusher endpoints Co-authored-by: Alexis Faizeau <a.faizeau@workadventu.re> Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: Piotr Hanusiak <wacneg@gmail.com>
2022-03-11 17:02:58 +01:00
import { menuIconVisiblilityStore, menuVisiblilityStore, warningContainerStore } from "../Stores/MenuStore";
import { localUserStore } from "./LocalUserStore";
import {
ServerToClientMessage as ServerToClientMessageTsProto,
TokenExpiredMessage,
WorldConnexionMessage,
ErrorMessage as ErrorMessageTsProto,
UserMovedMessage as UserMovedMessageTsProto,
GroupUpdateMessage as GroupUpdateMessageTsProto,
GroupDeleteMessage as GroupDeleteMessageTsProto,
UserJoinedMessage as UserJoinedMessageTsProto,
UserLeftMessage as UserLeftMessageTsProto,
EmoteEventMessage as EmoteEventMessageTsProto,
PlayerDetailsUpdatedMessage as PlayerDetailsUpdatedMessageTsProto,
WebRtcDisconnectMessage as WebRtcDisconnectMessageTsProto,
SendJitsiJwtMessage as SendJitsiJwtMessageTsProto,
ClientToServerMessage as ClientToServerMessageTsProto,
PositionMessage as PositionMessageTsProto,
ViewportMessage as ViewportMessageTsProto,
PositionMessage_Direction,
SetPlayerDetailsMessage as SetPlayerDetailsMessageTsProto,
PingMessage as PingMessageTsProto,
Refactoring Woka management (#1810) * Wrap websockets with HyperExpress * Add endpoints on pusher to resolve wokas * getting textures urls from pusher * Adding OpenAPI documentation for the pusher. The pusher now exposes a "/openapi" endpoint and a "/swagger-ui/" endpoint. * revert FRONT_URL * playerTextures metadata is being loaded via Phaser.Loader * fetch textures every time character or customize scene is open * Heavy changes: refactoring the pusher to always send the textures (and the front to accept them) * Sending character layer details to admin * Cleaning commented code * Fixing regex * Fix woka endpoints on pusher * Change error wording on pusher * Working on integration of the woka-list with the new admin endpoint. * Switching from "name" to "id" in texture object + using zod for woka/list validation * Add position on default woka data * Remove async on pusher option method * Fix woka list url * add options for /register * Fxiing loading the Woka list * Actually returning something in logout-callback * Copying messages to back too * remove customize button if no body parts are available (#1952) * remove customize button if no body parts are available * remove unused position field from PlayerTexturesCollection interface * removed unused label field * fix LocalUser test * little PlayerTextures class refactor * Fixing linting * Fixing missing Openapi packages in prod * Fixing back build Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: David Négrier <d.negrier@thecodingmachine.com> * Add returns on pusher endpoints Co-authored-by: Alexis Faizeau <a.faizeau@workadventu.re> Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: Piotr Hanusiak <wacneg@gmail.com>
2022-03-11 17:02:58 +01:00
CharacterLayerMessage,
2022-03-28 17:08:12 +02:00
} from "../Messages/ts-proto-generated/protos/messages";
import { Subject } from "rxjs";
Refactoring Woka management (#1810) * Wrap websockets with HyperExpress * Add endpoints on pusher to resolve wokas * getting textures urls from pusher * Adding OpenAPI documentation for the pusher. The pusher now exposes a "/openapi" endpoint and a "/swagger-ui/" endpoint. * revert FRONT_URL * playerTextures metadata is being loaded via Phaser.Loader * fetch textures every time character or customize scene is open * Heavy changes: refactoring the pusher to always send the textures (and the front to accept them) * Sending character layer details to admin * Cleaning commented code * Fixing regex * Fix woka endpoints on pusher * Change error wording on pusher * Working on integration of the woka-list with the new admin endpoint. * Switching from "name" to "id" in texture object + using zod for woka/list validation * Add position on default woka data * Remove async on pusher option method * Fix woka list url * add options for /register * Fxiing loading the Woka list * Actually returning something in logout-callback * Copying messages to back too * remove customize button if no body parts are available (#1952) * remove customize button if no body parts are available * remove unused position field from PlayerTexturesCollection interface * removed unused label field * fix LocalUser test * little PlayerTextures class refactor * Fixing linting * Fixing missing Openapi packages in prod * Fixing back build Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: David Négrier <d.negrier@thecodingmachine.com> * Add returns on pusher endpoints Co-authored-by: Alexis Faizeau <a.faizeau@workadventu.re> Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: Piotr Hanusiak <wacneg@gmail.com>
2022-03-11 17:02:58 +01:00
import { selectCharacterSceneVisibleStore } from "../Stores/SelectCharacterStore";
import { gameManager } from "../Phaser/Game/GameManager";
import { SelectCharacterScene, SelectCharacterSceneName } from "../Phaser/Login/SelectCharacterScene";
2020-09-25 18:29:22 +02:00
const manualPingDelay = 20000;
2020-09-25 18:29:22 +02:00
export class RoomConnection implements RoomConnection {
2020-09-28 18:52:54 +02:00
private readonly socket: WebSocket;
private userId: number | null = null;
2020-09-29 16:01:22 +02:00
private listeners: Map<string, Function[]> = new Map<string, Function[]>();
private static websocketFactory: null | ((url: string) => any) = null; // eslint-disable-line @typescript-eslint/no-explicit-any
2020-10-01 17:16:49 +02:00
private closed: boolean = false;
private tags: string[] = [];
private _userRoomToken: string | undefined;
2020-04-07 20:41:35 +02:00
private readonly _errorMessageStream = new Subject<ErrorMessageTsProto>();
public readonly errorMessageStream = this._errorMessageStream.asObservable();
private readonly _roomJoinedMessageStream = new Subject<{
connection: RoomConnection;
room: RoomJoinedMessageInterface;
}>();
public readonly roomJoinedMessageStream = this._roomJoinedMessageStream.asObservable();
private readonly _webRtcStartMessageStream = new Subject<UserSimplePeerInterface>();
public readonly webRtcStartMessageStream = this._webRtcStartMessageStream.asObservable();
private readonly _webRtcSignalToClientMessageStream = new Subject<WebRtcSignalReceivedMessageInterface>();
public readonly webRtcSignalToClientMessageStream = this._webRtcSignalToClientMessageStream.asObservable();
private readonly _webRtcScreenSharingSignalToClientMessageStream =
new Subject<WebRtcSignalReceivedMessageInterface>();
public readonly webRtcScreenSharingSignalToClientMessageStream =
this._webRtcScreenSharingSignalToClientMessageStream.asObservable();
private readonly _webRtcDisconnectMessageStream = new Subject<WebRtcDisconnectMessageTsProto>();
public readonly webRtcDisconnectMessageStream = this._webRtcDisconnectMessageStream.asObservable();
private readonly _teleportMessageMessageStream = new Subject<string>();
public readonly teleportMessageMessageStream = this._teleportMessageMessageStream.asObservable();
private readonly _sendJitsiJwtMessageStream = new Subject<SendJitsiJwtMessageTsProto>();
public readonly sendJitsiJwtMessageStream = this._sendJitsiJwtMessageStream.asObservable();
private readonly _worldFullMessageStream = new Subject<string | null>();
public readonly worldFullMessageStream = this._worldFullMessageStream.asObservable();
private readonly _worldConnexionMessageStream = new Subject<WorldConnexionMessage>();
public readonly worldConnexionMessageStream = this._worldConnexionMessageStream.asObservable();
private readonly _tokenExpiredMessageStream = new Subject<TokenExpiredMessage>();
public readonly tokenExpiredMessageStream = this._tokenExpiredMessageStream.asObservable();
private readonly _userMovedMessageStream = new Subject<UserMovedMessageTsProto>();
public readonly userMovedMessageStream = this._userMovedMessageStream.asObservable();
private readonly _groupUpdateMessageStream = new Subject<GroupCreatedUpdatedMessageInterface>();
public readonly groupUpdateMessageStream = this._groupUpdateMessageStream.asObservable();
2022-02-28 13:47:08 +01:00
private readonly _groupUsersUpdateMessageStream = new Subject<GroupUsersUpdateMessageInterface>();
public readonly groupUsersUpdateMessageStream = this._groupUsersUpdateMessageStream.asObservable();
private readonly _groupDeleteMessageStream = new Subject<GroupDeleteMessageTsProto>();
public readonly groupDeleteMessageStream = this._groupDeleteMessageStream.asObservable();
private readonly _userJoinedMessageStream = new Subject<MessageUserJoined>();
public readonly userJoinedMessageStream = this._userJoinedMessageStream.asObservable();
private readonly _userLeftMessageStream = new Subject<UserLeftMessageTsProto>();
public readonly userLeftMessageStream = this._userLeftMessageStream.asObservable();
private readonly _itemEventMessageStream = new Subject<{
itemId: number;
event: string;
parameters: unknown;
state: unknown;
}>();
public readonly itemEventMessageStream = this._itemEventMessageStream.asObservable();
private readonly _emoteEventMessageStream = new Subject<EmoteEventMessageTsProto>();
public readonly emoteEventMessageStream = this._emoteEventMessageStream.asObservable();
private readonly _variableMessageStream = new Subject<{ name: string; value: unknown }>();
public readonly variableMessageStream = this._variableMessageStream.asObservable();
private readonly _playerDetailsUpdatedMessageStream = new Subject<PlayerDetailsUpdatedMessageTsProto>();
public readonly playerDetailsUpdatedMessageStream = this._playerDetailsUpdatedMessageStream.asObservable();
private readonly _connectionErrorStream = new Subject<CloseEvent>();
public readonly connectionErrorStream = this._connectionErrorStream.asObservable();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public static setWebsocketFactory(websocketFactory: (url: string) => any): void {
RoomConnection.websocketFactory = websocketFactory;
2020-09-28 18:52:54 +02:00
}
/**
*
* @param token A JWT token containing the email of the user
* @param roomUrl The URL of the room in the form "https://example.com/_/[instance]/[map_url]" or "https://example.com/@/[org]/[event]/[map]"
Active authentication Oauth (#1377) * Active authentication Oauth - Google authentication - GitHub authentication - Linkedin authentication Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Finish connexion et get user info connexion Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Fix lint error Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Change the expires token for 30 days Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Update connexion stratgey - Set last room when it will be created and not when connexion is openned - Add '/login' end point permit to logout and open iframe to log user - Add logout feature permit to logout in front Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Implement logout and revoke token with hydra Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Fix pull develop conflict Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Profile url (#1399) * Create function that permit to get profile URL Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Continue profil user Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Add menu and logout button Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Update last room use Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Profile callback permit to get url profile setting from admin Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Finish profile show Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Delete profileUrl will be not use today Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Correct lint Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Update size of iframe Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Delete console log Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com> * Update feedback ARP Signed-off-by: Gregoire Parant <g.parant@thecodingmachine.com>
2021-09-05 18:17:49 +02:00
* @param name
* @param characterLayers
* @param position
* @param viewport
* @param companion
*/
public constructor(
token: string | null,
roomUrl: string,
name: string,
characterLayers: string[],
position: PositionInterface,
viewport: ViewportInterface,
companion: string | null
) {
let url = new URL(PUSHER_URL, window.location.toString()).toString();
url = url.replace("http://", "ws://").replace("https://", "wss://");
if (!url.endsWith("/")) {
url += "/";
}
url += "room";
2021-07-15 17:12:54 +02:00
url += "?roomId=" + encodeURIComponent(roomUrl);
url += "&token=" + (token ? encodeURIComponent(token) : "");
url += "&name=" + encodeURIComponent(name);
2020-10-09 17:14:03 +02:00
for (const layer of characterLayers) {
url += "&characterLayers=" + encodeURIComponent(layer);
}
url += "&x=" + Math.floor(position.x);
url += "&y=" + Math.floor(position.y);
url += "&top=" + Math.floor(viewport.top);
url += "&bottom=" + Math.floor(viewport.bottom);
url += "&left=" + Math.floor(viewport.left);
url += "&right=" + Math.floor(viewport.right);
if (typeof companion === "string") {
url += "&companion=" + encodeURIComponent(companion);
2021-04-02 21:21:11 +02:00
}
if (RoomConnection.websocketFactory) {
this.socket = RoomConnection.websocketFactory(url);
2020-09-28 18:52:54 +02:00
} else {
this.socket = new WebSocket(url);
}
this.socket.binaryType = "arraybuffer";
2020-09-28 18:52:54 +02:00
let interval: ReturnType<typeof setInterval> | undefined = undefined;
this.socket.onopen = () => {
//we manually ping every 20s to not be logged out by the server, even when the game is in background.
const pingMessage = PingMessageTsProto.encode({}).finish();
interval = setInterval(() => this.socket.send(pingMessage), manualPingDelay);
2020-09-28 18:52:54 +02:00
};
this.socket.addEventListener("close", (event) => {
if (interval) {
clearInterval(interval);
}
// If we are not connected yet (if a JoinRoomMessage was not sent), we need to retry.
if (this.userId === null && !this.closed) {
this._connectionErrorStream.next(event);
}
});
2020-09-28 18:52:54 +02:00
this.socket.onmessage = (messageEvent) => {
const arrayBuffer: ArrayBuffer = messageEvent.data;
2022-03-23 10:47:46 +01:00
const initCharacterLayers = characterLayers;
2020-09-28 18:52:54 +02:00
const serverToClientMessage = ServerToClientMessageTsProto.decode(new Uint8Array(arrayBuffer));
//const message = ServerToClientMessage.deserializeBinary(new Uint8Array(arrayBuffer));
const message = serverToClientMessage.message;
if (message === undefined) {
return;
}
switch (message.$case) {
case "batchMessage": {
for (const subMessageWrapper of message.batchMessage.payload) {
const subMessage = subMessageWrapper.message;
if (subMessage === undefined) {
return;
}
switch (subMessage.$case) {
case "errorMessage": {
this._errorMessageStream.next(subMessage.errorMessage);
console.error("An error occurred server side: " + subMessage.errorMessage.message);
break;
}
case "userJoinedMessage": {
this._userJoinedMessageStream.next(
this.toMessageUserJoined(subMessage.userJoinedMessage)
);
break;
}
case "userLeftMessage": {
this._userLeftMessageStream.next(subMessage.userLeftMessage);
break;
}
case "userMovedMessage": {
this._userMovedMessageStream.next(subMessage.userMovedMessage);
break;
}
case "groupUpdateMessage": {
this._groupUpdateMessageStream.next(
this.toGroupCreatedUpdatedMessage(subMessage.groupUpdateMessage)
);
break;
}
case "groupDeleteMessage": {
this._groupDeleteMessageStream.next(subMessage.groupDeleteMessage);
break;
}
case "itemEventMessage": {
this._itemEventMessageStream.next({
itemId: subMessage.itemEventMessage.itemId,
event: subMessage.itemEventMessage.event,
parameters: JSON.parse(subMessage.itemEventMessage.parametersJson),
state: JSON.parse(subMessage.itemEventMessage.stateJson),
});
break;
}
case "emoteEventMessage": {
this._emoteEventMessageStream.next(subMessage.emoteEventMessage);
break;
}
case "playerDetailsUpdatedMessage": {
this._playerDetailsUpdatedMessageStream.next(subMessage.playerDetailsUpdatedMessage);
break;
}
case "variableMessage": {
const name = subMessage.variableMessage.name;
const serializedValue = subMessage.variableMessage.value;
let value: unknown = undefined;
if (serializedValue) {
try {
value = JSON.parse(serializedValue);
} catch (e) {
console.error(
'Unable to unserialize value received from server for variable "' +
name +
'". Value received: "' +
serializedValue +
'". Error: ',
e
);
}
}
this._variableMessageStream.next({ name, value });
break;
}
default: {
// Security check: if we forget a "case", the line below will catch the error at compile-time.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const tmp: never = subMessage;
}
}
}
break;
}
case "roomJoinedMessage": {
const roomJoinedMessage = message.roomJoinedMessage;
2020-09-28 18:52:54 +02:00
const items: { [itemId: number]: unknown } = {};
for (const item of roomJoinedMessage.item) {
items[item.itemId] = JSON.parse(item.stateJson);
}
2020-09-28 18:52:54 +02:00
const variables = new Map<string, unknown>();
for (const variable of roomJoinedMessage.variable) {
try {
variables.set(variable.name, JSON.parse(variable.value));
} catch (e) {
console.error(
'Unable to unserialize value received from server for variable "' +
variable.name +
'". Value received: "' +
variable.value +
'". Error: ',
e
);
}
}
this.userId = roomJoinedMessage.currentUserId;
this.tags = roomJoinedMessage.tag;
this._userRoomToken = roomJoinedMessage.userRoomToken;
Refactoring Woka management (#1810) * Wrap websockets with HyperExpress * Add endpoints on pusher to resolve wokas * getting textures urls from pusher * Adding OpenAPI documentation for the pusher. The pusher now exposes a "/openapi" endpoint and a "/swagger-ui/" endpoint. * revert FRONT_URL * playerTextures metadata is being loaded via Phaser.Loader * fetch textures every time character or customize scene is open * Heavy changes: refactoring the pusher to always send the textures (and the front to accept them) * Sending character layer details to admin * Cleaning commented code * Fixing regex * Fix woka endpoints on pusher * Change error wording on pusher * Working on integration of the woka-list with the new admin endpoint. * Switching from "name" to "id" in texture object + using zod for woka/list validation * Add position on default woka data * Remove async on pusher option method * Fix woka list url * add options for /register * Fxiing loading the Woka list * Actually returning something in logout-callback * Copying messages to back too * remove customize button if no body parts are available (#1952) * remove customize button if no body parts are available * remove unused position field from PlayerTexturesCollection interface * removed unused label field * fix LocalUser test * little PlayerTextures class refactor * Fixing linting * Fixing missing Openapi packages in prod * Fixing back build Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: David Négrier <d.negrier@thecodingmachine.com> * Add returns on pusher endpoints Co-authored-by: Alexis Faizeau <a.faizeau@workadventu.re> Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: Piotr Hanusiak <wacneg@gmail.com>
2022-03-11 17:02:58 +01:00
// If one of the URLs sent to us does not exist, let's go to the Woka selection screen.
2022-03-23 10:47:46 +01:00
if (
roomJoinedMessage.characterLayer.length !== initCharacterLayers.length ||
roomJoinedMessage.characterLayer.find((layer) => !layer.url)
) {
this.goToSelectYourWokaScene();
this.closed = true;
Refactoring Woka management (#1810) * Wrap websockets with HyperExpress * Add endpoints on pusher to resolve wokas * getting textures urls from pusher * Adding OpenAPI documentation for the pusher. The pusher now exposes a "/openapi" endpoint and a "/swagger-ui/" endpoint. * revert FRONT_URL * playerTextures metadata is being loaded via Phaser.Loader * fetch textures every time character or customize scene is open * Heavy changes: refactoring the pusher to always send the textures (and the front to accept them) * Sending character layer details to admin * Cleaning commented code * Fixing regex * Fix woka endpoints on pusher * Change error wording on pusher * Working on integration of the woka-list with the new admin endpoint. * Switching from "name" to "id" in texture object + using zod for woka/list validation * Add position on default woka data * Remove async on pusher option method * Fix woka list url * add options for /register * Fxiing loading the Woka list * Actually returning something in logout-callback * Copying messages to back too * remove customize button if no body parts are available (#1952) * remove customize button if no body parts are available * remove unused position field from PlayerTexturesCollection interface * removed unused label field * fix LocalUser test * little PlayerTextures class refactor * Fixing linting * Fixing missing Openapi packages in prod * Fixing back build Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: David Négrier <d.negrier@thecodingmachine.com> * Add returns on pusher endpoints Co-authored-by: Alexis Faizeau <a.faizeau@workadventu.re> Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: Piotr Hanusiak <wacneg@gmail.com>
2022-03-11 17:02:58 +01:00
}
Refactoring Woka management (#1810) * Wrap websockets with HyperExpress * Add endpoints on pusher to resolve wokas * getting textures urls from pusher * Adding OpenAPI documentation for the pusher. The pusher now exposes a "/openapi" endpoint and a "/swagger-ui/" endpoint. * revert FRONT_URL * playerTextures metadata is being loaded via Phaser.Loader * fetch textures every time character or customize scene is open * Heavy changes: refactoring the pusher to always send the textures (and the front to accept them) * Sending character layer details to admin * Cleaning commented code * Fixing regex * Fix woka endpoints on pusher * Change error wording on pusher * Working on integration of the woka-list with the new admin endpoint. * Switching from "name" to "id" in texture object + using zod for woka/list validation * Add position on default woka data * Remove async on pusher option method * Fix woka list url * add options for /register * Fxiing loading the Woka list * Actually returning something in logout-callback * Copying messages to back too * remove customize button if no body parts are available (#1952) * remove customize button if no body parts are available * remove unused position field from PlayerTexturesCollection interface * removed unused label field * fix LocalUser test * little PlayerTextures class refactor * Fixing linting * Fixing missing Openapi packages in prod * Fixing back build Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: David Négrier <d.negrier@thecodingmachine.com> * Add returns on pusher endpoints Co-authored-by: Alexis Faizeau <a.faizeau@workadventu.re> Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: Piotr Hanusiak <wacneg@gmail.com>
2022-03-11 17:02:58 +01:00
if (this.closed) {
this.closeConnection();
Refactoring Woka management (#1810) * Wrap websockets with HyperExpress * Add endpoints on pusher to resolve wokas * getting textures urls from pusher * Adding OpenAPI documentation for the pusher. The pusher now exposes a "/openapi" endpoint and a "/swagger-ui/" endpoint. * revert FRONT_URL * playerTextures metadata is being loaded via Phaser.Loader * fetch textures every time character or customize scene is open * Heavy changes: refactoring the pusher to always send the textures (and the front to accept them) * Sending character layer details to admin * Cleaning commented code * Fixing regex * Fix woka endpoints on pusher * Change error wording on pusher * Working on integration of the woka-list with the new admin endpoint. * Switching from "name" to "id" in texture object + using zod for woka/list validation * Add position on default woka data * Remove async on pusher option method * Fix woka list url * add options for /register * Fxiing loading the Woka list * Actually returning something in logout-callback * Copying messages to back too * remove customize button if no body parts are available (#1952) * remove customize button if no body parts are available * remove unused position field from PlayerTexturesCollection interface * removed unused label field * fix LocalUser test * little PlayerTextures class refactor * Fixing linting * Fixing missing Openapi packages in prod * Fixing back build Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: David Négrier <d.negrier@thecodingmachine.com> * Add returns on pusher endpoints Co-authored-by: Alexis Faizeau <a.faizeau@workadventu.re> Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: Piotr Hanusiak <wacneg@gmail.com>
2022-03-11 17:02:58 +01:00
break;
}
const characterLayers = roomJoinedMessage.characterLayer.map(
this.mapCharacterLayerToBodyResourceDescription.bind(this)
);
this._roomJoinedMessageStream.next({
connection: this,
room: {
items,
variables,
Refactoring Woka management (#1810) * Wrap websockets with HyperExpress * Add endpoints on pusher to resolve wokas * getting textures urls from pusher * Adding OpenAPI documentation for the pusher. The pusher now exposes a "/openapi" endpoint and a "/swagger-ui/" endpoint. * revert FRONT_URL * playerTextures metadata is being loaded via Phaser.Loader * fetch textures every time character or customize scene is open * Heavy changes: refactoring the pusher to always send the textures (and the front to accept them) * Sending character layer details to admin * Cleaning commented code * Fixing regex * Fix woka endpoints on pusher * Change error wording on pusher * Working on integration of the woka-list with the new admin endpoint. * Switching from "name" to "id" in texture object + using zod for woka/list validation * Add position on default woka data * Remove async on pusher option method * Fix woka list url * add options for /register * Fxiing loading the Woka list * Actually returning something in logout-callback * Copying messages to back too * remove customize button if no body parts are available (#1952) * remove customize button if no body parts are available * remove unused position field from PlayerTexturesCollection interface * removed unused label field * fix LocalUser test * little PlayerTextures class refactor * Fixing linting * Fixing missing Openapi packages in prod * Fixing back build Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: David Négrier <d.negrier@thecodingmachine.com> * Add returns on pusher endpoints Co-authored-by: Alexis Faizeau <a.faizeau@workadventu.re> Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: Piotr Hanusiak <wacneg@gmail.com>
2022-03-11 17:02:58 +01:00
characterLayers,
} as RoomJoinedMessageInterface,
});
break;
}
case "worldFullMessage": {
this._worldFullMessageStream.next(null);
this.closed = true;
break;
}
Refactoring Woka management (#1810) * Wrap websockets with HyperExpress * Add endpoints on pusher to resolve wokas * getting textures urls from pusher * Adding OpenAPI documentation for the pusher. The pusher now exposes a "/openapi" endpoint and a "/swagger-ui/" endpoint. * revert FRONT_URL * playerTextures metadata is being loaded via Phaser.Loader * fetch textures every time character or customize scene is open * Heavy changes: refactoring the pusher to always send the textures (and the front to accept them) * Sending character layer details to admin * Cleaning commented code * Fixing regex * Fix woka endpoints on pusher * Change error wording on pusher * Working on integration of the woka-list with the new admin endpoint. * Switching from "name" to "id" in texture object + using zod for woka/list validation * Add position on default woka data * Remove async on pusher option method * Fix woka list url * add options for /register * Fxiing loading the Woka list * Actually returning something in logout-callback * Copying messages to back too * remove customize button if no body parts are available (#1952) * remove customize button if no body parts are available * remove unused position field from PlayerTexturesCollection interface * removed unused label field * fix LocalUser test * little PlayerTextures class refactor * Fixing linting * Fixing missing Openapi packages in prod * Fixing back build Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: David Négrier <d.negrier@thecodingmachine.com> * Add returns on pusher endpoints Co-authored-by: Alexis Faizeau <a.faizeau@workadventu.re> Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: Piotr Hanusiak <wacneg@gmail.com>
2022-03-11 17:02:58 +01:00
case "invalidTextureMessage": {
this.goToSelectYourWokaScene();
this.closed = true;
break;
}
case "tokenExpiredMessage": {
2022-01-04 16:48:47 +01:00
connectionManager.logout().catch((e) => console.error(e));
this.closed = true; //technically, this isn't needed since loadOpenIDScreen() will do window.location.assign() but I prefer to leave it for consistency
break;
}
case "worldConnexionMessage": {
this._worldFullMessageStream.next(message.worldConnexionMessage.message);
this.closed = true;
break;
}
case "webRtcSignalToClientMessage": {
this._webRtcSignalToClientMessageStream.next({
userId: message.webRtcSignalToClientMessage.userId,
signal: JSON.parse(message.webRtcSignalToClientMessage.signal),
webRtcUser: message.webRtcSignalToClientMessage.webrtcUserName
? message.webRtcSignalToClientMessage.webrtcUserName
: undefined,
webRtcPassword: message.webRtcSignalToClientMessage.webrtcPassword
? message.webRtcSignalToClientMessage.webrtcPassword
: undefined,
});
break;
}
case "webRtcScreenSharingSignalToClientMessage": {
this._webRtcScreenSharingSignalToClientMessageStream.next({
userId: message.webRtcScreenSharingSignalToClientMessage.userId,
signal: JSON.parse(message.webRtcScreenSharingSignalToClientMessage.signal),
webRtcUser: message.webRtcScreenSharingSignalToClientMessage.webrtcUserName
? message.webRtcScreenSharingSignalToClientMessage.webrtcUserName
: undefined,
webRtcPassword: message.webRtcScreenSharingSignalToClientMessage.webrtcPassword
? message.webRtcScreenSharingSignalToClientMessage.webrtcPassword
: undefined,
});
break;
}
case "webRtcStartMessage": {
this._webRtcStartMessageStream.next({
userId: message.webRtcStartMessage.userId,
initiator: message.webRtcStartMessage.initiator,
webRtcUser: message.webRtcStartMessage.webrtcUserName
? message.webRtcStartMessage.webrtcUserName
: undefined,
webRtcPassword: message.webRtcStartMessage.webrtcPassword
? message.webRtcStartMessage.webrtcPassword
: undefined,
});
break;
}
case "webRtcDisconnectMessage": {
this._webRtcDisconnectMessageStream.next(message.webRtcDisconnectMessage);
break;
}
case "teleportMessageMessage": {
// FIXME: WHY IS THIS UNUSED? CAN WE REMOVE THIS???
this._teleportMessageMessageStream.next(message.teleportMessageMessage.map);
break;
}
case "sendJitsiJwtMessage": {
this._sendJitsiJwtMessageStream.next(message.sendJitsiJwtMessage);
break;
}
2022-02-28 13:47:08 +01:00
case "groupUsersUpdateMessage": {
this._groupUsersUpdateMessageStream.next(message.groupUsersUpdateMessage);
break;
}
case "sendUserMessage": {
adminMessagesService.onSendusermessage(message.sendUserMessage);
break;
}
case "banUserMessage": {
adminMessagesService.onSendusermessage(message.banUserMessage);
break;
}
case "worldFullWarningMessage": {
warningContainerStore.activateWarningContainer();
break;
}
case "refreshRoomMessage": {
//todo: implement a way to notify the user the room was refreshed.
break;
}
case "followRequestMessage": {
if (!localUserStore.getIgnoreFollowRequests()) {
followUsersStore.addFollowRequest(message.followRequestMessage.leader);
}
break;
}
case "followConfirmationMessage": {
followUsersStore.addFollower(message.followConfirmationMessage.follower);
break;
}
case "followAbortMessage": {
if (get(followRoleStore) === "follower") {
followUsersStore.stopFollowing();
} else {
followUsersStore.removeFollower(message.followAbortMessage.follower);
}
break;
}
case "errorMessage": {
this._errorMessageStream.next(message.errorMessage);
console.error("An error occurred server side: " + message.errorMessage.message);
break;
}
default: {
// Security check: if we forget a "case", the line below will catch the error at compile-time.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const tmp: never = message;
}
}
};
}
2020-09-29 16:01:22 +02:00
private dispatch(event: string, payload: unknown): void {
const listeners = this.listeners.get(event);
if (listeners === undefined) {
return;
}
for (const listener of listeners) {
listener(payload);
}
}
/*public emitPlayerDetailsMessage(userName: string, characterLayersSelected: BodyResourceDescriptionInterface[]) {
2020-09-25 18:29:22 +02:00
const message = new SetPlayerDetailsMessage();
2020-09-29 17:24:16 +02:00
message.setName(userName);
2020-10-20 16:39:23 +02:00
message.setCharacterlayersList(characterLayersSelected.map((characterLayer) => characterLayer.name));
2020-06-22 16:10:18 +02:00
const clientToServerMessage = new ClientToServerMessage();
clientToServerMessage.setSetplayerdetailsmessage(message);
2020-09-28 18:52:54 +02:00
this.socket.send(clientToServerMessage.serializeBinary().buffer);
}*/
public emitPlayerShowVoiceIndicator(show: boolean): void {
const message = SetPlayerDetailsMessageTsProto.fromPartial({
showVoiceIndicator: show,
});
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "setPlayerDetailsMessage",
setPlayerDetailsMessage: message,
},
}).finish();
this.socket.send(bytes);
}
public emitPlayerAway(away: boolean): void {
const message = SetPlayerDetailsMessageTsProto.fromPartial({
away,
});
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "setPlayerDetailsMessage",
setPlayerDetailsMessage: message,
},
}).finish();
this.socket.send(bytes);
}
public emitPlayerOutlineColor(color: number | null) {
let message: SetPlayerDetailsMessageTsProto;
if (color === null) {
message = SetPlayerDetailsMessageTsProto.fromPartial({
removeOutlineColor: true,
});
} else {
message = SetPlayerDetailsMessageTsProto.fromPartial({
outlineColor: color,
});
}
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "setPlayerDetailsMessage",
setPlayerDetailsMessage: message,
},
}).finish();
this.socket.send(bytes);
}
public closeConnection(): void {
this.socket?.close();
2020-10-01 17:16:49 +02:00
this.closed = true;
2020-06-03 11:55:31 +02:00
}
private toPositionMessage(x: number, y: number, direction: string, moving: boolean): PositionMessageTsProto {
return {
x: Math.floor(x),
y: Math.floor(y),
moving,
direction: (() => {
switch (direction) {
case "up":
return PositionMessage_Direction.UP;
case "down":
return PositionMessage_Direction.DOWN;
case "left":
return PositionMessage_Direction.LEFT;
case "right":
return PositionMessage_Direction.RIGHT;
default:
throw new Error("Unexpected direction");
}
})(),
};
2020-09-28 18:52:54 +02:00
}
private toViewportMessage(viewport: ViewportInterface): ViewportMessageTsProto {
return {
left: Math.floor(viewport.left),
right: Math.floor(viewport.right),
top: Math.floor(viewport.top),
bottom: Math.floor(viewport.bottom),
};
2020-09-28 18:52:54 +02:00
}
public sharePosition(x: number, y: number, direction: string, moving: boolean, viewport: ViewportInterface): void {
if (!this.socket) {
2020-09-28 18:52:54 +02:00
return;
}
const positionMessage = this.toPositionMessage(x, y, direction, moving);
const viewportMessage = this.toViewportMessage(viewport);
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "userMovesMessage",
userMovesMessage: {
position: positionMessage,
viewport: viewportMessage,
},
},
}).finish();
2020-09-24 10:05:16 +02:00
this.socket.send(bytes);
}
public setSilent(silent: boolean): void {
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "silentMessage",
silentMessage: {
silent,
},
},
}).finish();
2020-09-28 18:52:54 +02:00
this.socket.send(bytes);
}
public setViewport(viewport: ViewportInterface): void {
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "viewportMessage",
viewportMessage: this.toViewportMessage(viewport),
},
}).finish();
2020-09-28 18:52:54 +02:00
this.socket.send(bytes);
}
/* public onUserJoins(callback: (message: MessageUserJoined) => void): void {
2020-09-29 16:01:22 +02:00
this.onMessage(EventMessage.JOIN_ROOM, (message: UserJoinedMessage) => {
2020-09-28 18:52:54 +02:00
callback(this.toMessageUserJoined(message));
2020-09-24 14:50:28 +02:00
});
}*/
Refactoring Woka management (#1810) * Wrap websockets with HyperExpress * Add endpoints on pusher to resolve wokas * getting textures urls from pusher * Adding OpenAPI documentation for the pusher. The pusher now exposes a "/openapi" endpoint and a "/swagger-ui/" endpoint. * revert FRONT_URL * playerTextures metadata is being loaded via Phaser.Loader * fetch textures every time character or customize scene is open * Heavy changes: refactoring the pusher to always send the textures (and the front to accept them) * Sending character layer details to admin * Cleaning commented code * Fixing regex * Fix woka endpoints on pusher * Change error wording on pusher * Working on integration of the woka-list with the new admin endpoint. * Switching from "name" to "id" in texture object + using zod for woka/list validation * Add position on default woka data * Remove async on pusher option method * Fix woka list url * add options for /register * Fxiing loading the Woka list * Actually returning something in logout-callback * Copying messages to back too * remove customize button if no body parts are available (#1952) * remove customize button if no body parts are available * remove unused position field from PlayerTexturesCollection interface * removed unused label field * fix LocalUser test * little PlayerTextures class refactor * Fixing linting * Fixing missing Openapi packages in prod * Fixing back build Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: David Négrier <d.negrier@thecodingmachine.com> * Add returns on pusher endpoints Co-authored-by: Alexis Faizeau <a.faizeau@workadventu.re> Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: Piotr Hanusiak <wacneg@gmail.com>
2022-03-11 17:02:58 +01:00
private mapCharacterLayerToBodyResourceDescription(
characterLayer: CharacterLayerMessage
): BodyResourceDescriptionInterface {
return {
id: characterLayer.name,
img: characterLayer.url,
};
}
2020-09-28 18:52:54 +02:00
// TODO: move this to protobuf utils
private toMessageUserJoined(message: UserJoinedMessageTsProto): MessageUserJoined {
const position = message.position;
2020-09-28 18:52:54 +02:00
if (position === undefined) {
throw new Error("Invalid JOIN_ROOM message");
2020-09-28 18:52:54 +02:00
}
2020-10-20 16:39:23 +02:00
Refactoring Woka management (#1810) * Wrap websockets with HyperExpress * Add endpoints on pusher to resolve wokas * getting textures urls from pusher * Adding OpenAPI documentation for the pusher. The pusher now exposes a "/openapi" endpoint and a "/swagger-ui/" endpoint. * revert FRONT_URL * playerTextures metadata is being loaded via Phaser.Loader * fetch textures every time character or customize scene is open * Heavy changes: refactoring the pusher to always send the textures (and the front to accept them) * Sending character layer details to admin * Cleaning commented code * Fixing regex * Fix woka endpoints on pusher * Change error wording on pusher * Working on integration of the woka-list with the new admin endpoint. * Switching from "name" to "id" in texture object + using zod for woka/list validation * Add position on default woka data * Remove async on pusher option method * Fix woka list url * add options for /register * Fxiing loading the Woka list * Actually returning something in logout-callback * Copying messages to back too * remove customize button if no body parts are available (#1952) * remove customize button if no body parts are available * remove unused position field from PlayerTexturesCollection interface * removed unused label field * fix LocalUser test * little PlayerTextures class refactor * Fixing linting * Fixing missing Openapi packages in prod * Fixing back build Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: David Négrier <d.negrier@thecodingmachine.com> * Add returns on pusher endpoints Co-authored-by: Alexis Faizeau <a.faizeau@workadventu.re> Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: Piotr Hanusiak <wacneg@gmail.com>
2022-03-11 17:02:58 +01:00
const characterLayers = message.characterLayers.map(this.mapCharacterLayerToBodyResourceDescription.bind(this));
2020-10-20 16:39:23 +02:00
const companion = message.companion;
2021-04-02 21:21:11 +02:00
2020-09-28 18:52:54 +02:00
return {
userId: message.userId,
name: message.name,
2020-10-20 16:39:23 +02:00
characterLayers,
visitCardUrl: message.visitCardUrl,
2021-04-02 21:21:11 +02:00
position: ProtobufClientUtils.toPointInterface(position),
away: message.away,
companion: companion ? companion.name : null,
userUuid: message.userUuid,
outlineColor: message.hasOutline ? message.outlineColor : undefined,
};
2020-09-28 18:52:54 +02:00
}
/**
* Registers a listener on a message that is part of a batch
*/
2020-09-29 16:01:22 +02:00
private onMessage(eventName: string, callback: Function): void {
let callbacks = this.listeners.get(eventName);
if (callbacks === undefined) {
callbacks = new Array<Function>();
2020-09-29 16:01:22 +02:00
this.listeners.set(eventName, callbacks);
}
callbacks.push(callback);
}
private toGroupCreatedUpdatedMessage(message: GroupUpdateMessageTsProto): GroupCreatedUpdatedMessageInterface {
const position = message.position;
2020-09-28 18:52:54 +02:00
if (position === undefined) {
throw new Error("Missing position in GROUP_CREATE_UPDATE");
2020-09-28 18:52:54 +02:00
}
2020-09-21 11:24:03 +02:00
2020-09-28 18:52:54 +02:00
return {
groupId: message.groupId,
position: position,
groupSize: message.groupSize,
locked: message.locked,
};
}
2020-09-28 18:52:54 +02:00
public onConnectError(callback: (error: Event) => void): void {
this.socket.addEventListener("error", callback);
2020-09-28 18:52:54 +02:00
}
public sendWebrtcSignal(signal: unknown, receiverId: number) {
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "webRtcSignalToServerMessage",
webRtcSignalToServerMessage: {
receiverId,
signal: JSON.stringify(signal),
},
},
}).finish();
2020-09-29 16:01:22 +02:00
this.socket.send(bytes);
2020-04-25 16:05:33 +02:00
}
public sendWebrtcScreenSharingSignal(signal: unknown, receiverId: number) {
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "webRtcScreenSharingSignalToServerMessage",
webRtcScreenSharingSignalToServerMessage: {
receiverId,
signal: JSON.stringify(signal),
},
},
}).finish();
2020-04-25 16:05:33 +02:00
this.socket.send(bytes);
2020-04-25 16:05:33 +02:00
}
public onServerDisconnected(callback: () => void): void {
this.socket.addEventListener("close", (event) => {
if (this.closed === true || connectionManager.unloading) {
2020-10-01 17:16:49 +02:00
return;
}
console.log("Socket closed with code " + event.code + ". Reason: " + event.reason);
2020-09-28 18:52:54 +02:00
if (event.code === 1000) {
// Normal closure case
return;
}
callback();
2020-05-13 20:22:42 +02:00
});
}
public getUserId(): number {
if (this.userId === null) throw new Error("UserId cannot be null!");
return this.userId;
2020-05-13 20:22:42 +02:00
}
2020-09-24 17:24:37 +02:00
emitActionableEvent(itemId: number, event: string, state: unknown, parameters: unknown): void {
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "itemEventMessage",
itemEventMessage: {
itemId,
event,
stateJson: JSON.stringify(state),
parametersJson: JSON.stringify(parameters),
},
},
}).finish();
2020-09-24 17:24:37 +02:00
this.socket.send(bytes);
2020-07-27 22:36:07 +02:00
}
emitSetVariableEvent(name: string, value: unknown): void {
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "variableMessage",
variableMessage: {
name,
value: JSON.stringify(value),
},
},
}).finish();
this.socket.send(bytes);
}
public uploadAudio(file: FormData) {
return Axios.post(`${UPLOADER_URL}/upload-audio-message`, file)
.then((res: { data: {} }) => {
return res.data;
})
.catch((err) => {
console.error(err);
throw err;
});
}
public emitGlobalMessage(message: PlayGlobalMessageInterface): void {
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "playGlobalMessage",
playGlobalMessage: {
type: message.type,
content: message.content,
broadcastToWorld: message.broadcastToWorld,
},
},
}).finish();
this.socket.send(bytes);
}
2020-10-12 11:22:41 +02:00
public emitReportPlayerMessage(reportedUserUuid: string, reportComment: string): void {
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "reportPlayerMessage",
reportPlayerMessage: {
reportedUserUuid,
reportComment,
},
},
}).finish();
2020-10-12 11:22:41 +02:00
this.socket.send(bytes);
2020-10-12 11:22:41 +02:00
}
public emitQueryJitsiJwtMessage(jitsiRoom: string, tag: string | undefined): void {
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "queryJitsiJwtMessage",
queryJitsiJwtMessage: {
jitsiRoom,
tag: tag ?? "", // empty string is sent as "undefined" by ts-proto
// TODO: when we migrated "pusher" to ts-proto, migrate this to a StringValue
},
},
}).finish();
2020-10-16 19:13:26 +02:00
this.socket.send(bytes);
}
public hasTag(tag: string): boolean {
2020-10-14 11:48:34 +02:00
return this.tags.includes(tag);
}
public isAdmin(): boolean {
return this.hasTag("admin");
}
public emitEmoteEvent(emoteName: string): void {
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "emotePromptMessage",
emotePromptMessage: {
emote: emoteName,
},
},
}).finish();
this.socket.send(bytes);
}
2021-12-15 14:48:45 +01:00
public emitFollowRequest(): void {
if (!this.userId) {
return;
}
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "followRequestMessage",
followRequestMessage: {
leader: this.userId,
},
},
}).finish();
this.socket.send(bytes);
}
2021-12-15 14:48:45 +01:00
public emitFollowConfirmation(): void {
if (!this.userId) {
return;
}
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "followConfirmationMessage",
followConfirmationMessage: {
leader: get(followUsersStore)[0],
follower: this.userId,
},
},
}).finish();
this.socket.send(bytes);
}
2021-12-15 14:48:45 +01:00
public emitFollowAbort(): void {
const isLeader = get(followRoleStore) === "leader";
2021-12-15 14:48:45 +01:00
const hasFollowers = get(followUsersStore).length > 0;
if (!this.userId || (isLeader && !hasFollowers)) {
return;
}
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "followAbortMessage",
followAbortMessage: {
leader: isLeader ? this.userId : get(followUsersStore)[0],
follower: isLeader ? 0 : this.userId,
},
},
}).finish();
this.socket.send(bytes);
2021-12-12 00:24:39 +01:00
}
public emitLockGroup(lock: boolean = true): void {
const bytes = ClientToServerMessageTsProto.encode({
message: {
$case: "lockGroupPromptMessage",
lockGroupPromptMessage: {
lock,
},
},
}).finish();
this.socket.send(bytes);
}
public getAllTags(): string[] {
return this.tags;
}
public get userRoomToken(): string | undefined {
return this._userRoomToken;
}
Refactoring Woka management (#1810) * Wrap websockets with HyperExpress * Add endpoints on pusher to resolve wokas * getting textures urls from pusher * Adding OpenAPI documentation for the pusher. The pusher now exposes a "/openapi" endpoint and a "/swagger-ui/" endpoint. * revert FRONT_URL * playerTextures metadata is being loaded via Phaser.Loader * fetch textures every time character or customize scene is open * Heavy changes: refactoring the pusher to always send the textures (and the front to accept them) * Sending character layer details to admin * Cleaning commented code * Fixing regex * Fix woka endpoints on pusher * Change error wording on pusher * Working on integration of the woka-list with the new admin endpoint. * Switching from "name" to "id" in texture object + using zod for woka/list validation * Add position on default woka data * Remove async on pusher option method * Fix woka list url * add options for /register * Fxiing loading the Woka list * Actually returning something in logout-callback * Copying messages to back too * remove customize button if no body parts are available (#1952) * remove customize button if no body parts are available * remove unused position field from PlayerTexturesCollection interface * removed unused label field * fix LocalUser test * little PlayerTextures class refactor * Fixing linting * Fixing missing Openapi packages in prod * Fixing back build Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: David Négrier <d.negrier@thecodingmachine.com> * Add returns on pusher endpoints Co-authored-by: Alexis Faizeau <a.faizeau@workadventu.re> Co-authored-by: Hanusiak Piotr <piotr@ltmp.co> Co-authored-by: Piotr Hanusiak <wacneg@gmail.com>
2022-03-11 17:02:58 +01:00
private goToSelectYourWokaScene(): void {
menuVisiblilityStore.set(false);
menuIconVisiblilityStore.set(false);
selectCharacterSceneVisibleStore.set(true);
gameManager.leaveGame(SelectCharacterSceneName, new SelectCharacterScene());
}
}