2020-11-13 18:00:22 +01:00
import { PusherRoom } from "../Model/PusherRoom" ;
import { CharacterLayer , ExSocketInterface } from "../Model/Websocket/ExSocketInterface" ;
import {
GroupDeleteMessage ,
ItemEventMessage ,
PlayGlobalMessage ,
PositionMessage ,
RoomJoinedMessage ,
ServerToClientMessage ,
SetPlayerDetailsMessage ,
SilentMessage ,
SubMessage ,
ReportPlayerMessage ,
2020-12-10 17:46:15 +01:00
UserLeftMessage ,
2020-11-13 18:00:22 +01:00
UserMovesMessage ,
2020-12-10 17:46:15 +01:00
ViewportMessage ,
2020-11-13 18:00:22 +01:00
WebRtcSignalToServerMessage ,
QueryJitsiJwtMessage ,
SendJitsiJwtMessage ,
2020-12-10 17:46:15 +01:00
JoinRoomMessage ,
CharacterLayerMessage ,
PusherToBackMessage ,
AdminPusherToBackMessage ,
2021-01-17 03:07:46 +01:00
ServerToAdminClientMessage ,
2021-01-17 22:40:54 +01:00
SendUserMessage ,
2021-01-18 15:07:40 +01:00
BanUserMessage , UserJoinedRoomMessage , UserLeftRoomMessage
2020-11-13 18:00:22 +01:00
} from "../Messages/generated/messages_pb" ;
import { PointInterface } from "../Model/Websocket/PointInterface" ;
import { ProtobufUtils } from "../Model/Websocket/ProtobufUtils" ;
import { cpuTracker } from "./CpuTracker" ;
import { GROUP_RADIUS , JITSI_ISS , MINIMUM_DISTANCE , SECRET_JITSI_KEY } from "../Enum/EnvironmentVariable" ;
import { Movable } from "../Model/Movable" ;
import { PositionInterface } from "../Model/PositionInterface" ;
import { adminApi , CharacterTexture } from "./AdminApi" ;
import Direction = PositionMessage . Direction ;
import { emitError , emitInBatch } from "./IoSocketHelpers" ;
import Jwt from "jsonwebtoken" ;
import { JITSI_URL } from "../Enum/EnvironmentVariable" ;
import { clientEventsEmitter } from "./ClientEventsEmitter" ;
import { gaugeManager } from "./GaugeManager" ;
import { apiClientRepository } from "./ApiClientRepository" ;
import { ServiceError } from "grpc" ;
import { GroupDescriptor , UserDescriptor , ZoneEventListener } from "_Model/Zone" ;
import Debug from "debug" ;
2020-12-10 17:46:15 +01:00
import { ExAdminSocketInterface } from "_Model/Websocket/ExAdminSocketInterface" ;
2020-11-13 18:00:22 +01:00
const debug = Debug ( 'socket' ) ;
interface AdminSocketRoomsList {
[ index : string ] : number ;
}
interface AdminSocketUsersList {
[ index : string ] : boolean ;
}
export interface AdminSocketData {
rooms : AdminSocketRoomsList ,
users : AdminSocketUsersList ,
}
export class SocketManager implements ZoneEventListener {
private Worlds : Map < string , PusherRoom > = new Map < string , PusherRoom > ( ) ;
private sockets : Map < number , ExSocketInterface > = new Map < number , ExSocketInterface > ( ) ;
constructor ( ) {
clientEventsEmitter . registerToClientJoin ( ( clientUUid : string , roomId : string ) = > {
gaugeManager . incNbClientPerRoomGauge ( roomId ) ;
} ) ;
clientEventsEmitter . registerToClientLeave ( ( clientUUid : string , roomId : string ) = > {
gaugeManager . decNbClientPerRoomGauge ( roomId ) ;
} ) ;
}
2020-12-10 17:46:15 +01:00
async handleAdminRoom ( client : ExAdminSocketInterface , roomId : string ) : Promise < void > {
const apiClient = await apiClientRepository . getClient ( roomId ) ;
const adminRoomStream = apiClient . adminRoom ( ) ;
client . adminConnection = adminRoomStream ;
adminRoomStream . on ( 'data' , ( message : ServerToAdminClientMessage ) = > {
2021-01-18 15:07:40 +01:00
if ( message . hasUserjoinedroom ( ) ) {
const userJoinedRoomMessage = message . getUserjoinedroom ( ) as UserJoinedRoomMessage ;
2020-12-10 17:46:15 +01:00
if ( ! client . disconnecting ) {
2021-01-18 15:07:40 +01:00
client . send ( JSON . stringify ( {
type : 'MemberJoin' ,
data : {
uuid : userJoinedRoomMessage.getUuid ( ) ,
name : userJoinedRoomMessage.getName ( ) ,
ipAddress : userJoinedRoomMessage.getIpaddress ( ) ,
roomId : roomId ,
}
} ) ) ;
2020-12-10 17:46:15 +01:00
}
2021-01-18 15:07:40 +01:00
} else if ( message . hasUserleftroom ( ) ) {
const userLeftRoomMessage = message . getUserleftroom ( ) as UserLeftRoomMessage ;
2020-12-10 17:46:15 +01:00
if ( ! client . disconnecting ) {
2021-01-18 15:07:40 +01:00
client . send ( JSON . stringify ( {
type : 'MemberLeave' ,
data : {
uuid : userLeftRoomMessage.getUuid ( )
}
} ) ) ;
2020-12-10 17:46:15 +01:00
}
} else {
throw new Error ( 'Unexpected admin message' ) ;
}
} ) . on ( 'end' , ( ) = > {
console . warn ( 'Admin connection lost to back server' ) ;
// Let's close the front connection if the back connection is closed. This way, we can retry connecting from the start.
if ( ! client . disconnecting ) {
this . closeWebsocketConnection ( client , 1011 , 'Connection lost to back server' ) ;
}
console . log ( 'A user left' ) ;
} ) . on ( 'error' , ( err : Error ) = > {
console . error ( 'Error in connection to back server:' , err ) ;
if ( ! client . disconnecting ) {
this . closeWebsocketConnection ( client , 1011 , 'Error while connecting to back server' ) ;
}
} ) ;
const message = new AdminPusherToBackMessage ( ) ;
message . setSubscribetoroom ( roomId ) ;
adminRoomStream . write ( message ) ;
}
leaveAdminRoom ( socket : ExAdminSocketInterface ) {
if ( socket . adminConnection ) {
socket . adminConnection . end ( ) ;
}
}
2020-11-13 18:00:22 +01:00
getAdminSocketDataFor ( roomId :string ) : AdminSocketData {
throw new Error ( 'Not reimplemented yet' ) ;
/ * c o n s t d a t a : A d m i n S o c k e t D a t a = {
rooms : { } ,
users : { } ,
}
const room = this . Worlds . get ( roomId ) ;
if ( room === undefined ) {
return data ;
}
const users = room . getUsers ( ) ;
data . rooms [ roomId ] = users . size ;
users . forEach ( user = > {
data . users [ user . uuid ] = true
} )
return data ; * /
}
async handleJoinRoom ( client : ExSocketInterface ) : Promise < void > {
const viewport = client . viewport ;
try {
const joinRoomMessage = new JoinRoomMessage ( ) ;
2020-12-02 17:51:46 +01:00
joinRoomMessage . setUseruuid ( client . userUuid ) ;
2021-01-15 03:19:58 +01:00
joinRoomMessage . setIpaddress ( client . IPAddress ) ;
2020-11-13 18:00:22 +01:00
joinRoomMessage . setRoomid ( client . roomId ) ;
joinRoomMessage . setName ( client . name ) ;
joinRoomMessage . setPositionmessage ( ProtobufUtils . toPositionMessage ( client . position ) ) ;
2021-01-17 03:07:46 +01:00
joinRoomMessage . setTagList ( client . tags ) ;
2020-11-13 18:00:22 +01:00
for ( const characterLayer of client . characterLayers ) {
const characterLayerMessage = new CharacterLayerMessage ( ) ;
characterLayerMessage . setName ( characterLayer . name ) ;
if ( characterLayer . url !== undefined ) {
characterLayerMessage . setUrl ( characterLayer . url ) ;
}
joinRoomMessage . addCharacterlayer ( characterLayerMessage ) ;
}
console . log ( 'Calling joinRoom' )
const apiClient = await apiClientRepository . getClient ( client . roomId ) ;
const streamToPusher = apiClient . joinRoom ( ) ;
client . backConnection = streamToPusher ;
streamToPusher . on ( 'data' , ( message : ServerToClientMessage ) = > {
if ( message . hasRoomjoinedmessage ( ) ) {
2020-12-02 17:51:46 +01:00
client . userId = ( message . getRoomjoinedmessage ( ) as RoomJoinedMessage ) . getCurrentuserid ( ) ;
// TODO: do we need this.sockets anymore?
this . sockets . set ( client . userId , client ) ;
2020-11-13 18:00:22 +01:00
// If this is the first message sent, send back the viewport.
this . handleViewport ( client , viewport ) ;
}
// Let's pass data over from the back to the client.
if ( ! client . disconnecting ) {
client . send ( message . serializeBinary ( ) . buffer , true ) ;
}
} ) . on ( 'end' , ( ) = > {
console . warn ( 'Connection lost to back server' ) ;
// Let's close the front connection if the back connection is closed. This way, we can retry connecting from the start.
if ( ! client . disconnecting ) {
2020-12-03 16:39:44 +01:00
this . closeWebsocketConnection ( client , 1011 , 'Connection lost to back server' ) ;
2020-11-13 18:00:22 +01:00
}
console . log ( 'A user left' ) ;
} ) . on ( 'error' , ( err : Error ) = > {
console . error ( 'Error in connection to back server:' , err ) ;
if ( ! client . disconnecting ) {
2020-12-03 16:39:44 +01:00
this . closeWebsocketConnection ( client , 1011 , 'Error while connecting to back server' ) ;
2020-11-13 18:00:22 +01:00
}
} ) ;
const pusherToBackMessage = new PusherToBackMessage ( ) ;
pusherToBackMessage . setJoinroommessage ( joinRoomMessage ) ;
streamToPusher . write ( pusherToBackMessage ) ;
} catch ( e ) {
console . error ( 'An error occurred on "join_room" event' ) ;
console . error ( e ) ;
}
}
2020-12-10 17:46:15 +01:00
private closeWebsocketConnection ( client : ExSocketInterface | ExAdminSocketInterface , code : number , reason : string ) {
2020-11-13 18:00:22 +01:00
client . disconnecting = true ;
//this.leaveRoom(client);
2020-12-03 16:39:44 +01:00
//client.close();
client . end ( code , reason ) ;
2020-11-13 18:00:22 +01:00
}
handleViewport ( client : ExSocketInterface , viewport : ViewportMessage.AsObject ) {
try {
client . viewport = viewport ;
const world = this . Worlds . get ( client . roomId ) ;
if ( ! world ) {
console . error ( "In SET_VIEWPORT, could not find world with id '" , client . roomId , "'" ) ;
return ;
}
world . setViewport ( client , client . viewport ) ;
} catch ( e ) {
console . error ( 'An error occurred on "SET_VIEWPORT" event' ) ;
console . error ( e ) ;
}
}
handleUserMovesMessage ( client : ExSocketInterface , userMovesMessage : UserMovesMessage ) {
const pusherToBackMessage = new PusherToBackMessage ( ) ;
pusherToBackMessage . setUsermovesmessage ( userMovesMessage ) ;
client . backConnection . write ( pusherToBackMessage ) ;
const viewport = userMovesMessage . getViewport ( ) ;
if ( viewport === undefined ) {
throw new Error ( 'Missing viewport in UserMovesMessage' ) ;
}
// Now, we need to listen to the correct viewport.
this . handleViewport ( client , viewport . toObject ( ) )
}
// Useless now, will be useful again if we allow editing details in game
handleSetPlayerDetails ( client : ExSocketInterface , playerDetailsMessage : SetPlayerDetailsMessage ) {
const pusherToBackMessage = new PusherToBackMessage ( ) ;
pusherToBackMessage . setSetplayerdetailsmessage ( playerDetailsMessage ) ;
client . backConnection . write ( pusherToBackMessage ) ;
}
handleSilentMessage ( client : ExSocketInterface , silentMessage : SilentMessage ) {
const pusherToBackMessage = new PusherToBackMessage ( ) ;
pusherToBackMessage . setSilentmessage ( silentMessage ) ;
client . backConnection . write ( pusherToBackMessage ) ;
}
handleItemEvent ( client : ExSocketInterface , itemEventMessage : ItemEventMessage ) {
const pusherToBackMessage = new PusherToBackMessage ( ) ;
pusherToBackMessage . setItemeventmessage ( itemEventMessage ) ;
client . backConnection . write ( pusherToBackMessage ) ;
/ * c o n s t i t e m E v e n t = P r o t o b u f U t i l s . t o I t e m E v e n t ( i t e m E v e n t M e s s a g e ) ;
try {
const world = this . Worlds . get ( ws . roomId ) ;
if ( ! world ) {
console . error ( "Could not find world with id '" , ws . roomId , "'" ) ;
return ;
}
const subMessage = new SubMessage ( ) ;
subMessage . setItemeventmessage ( itemEventMessage ) ;
// Let's send the event without using the SocketIO room.
for ( const user of world . getUsers ( ) . values ( ) ) {
const client = this . searchClientByIdOrFail ( user . id ) ;
//client.emit(SocketIoEvent.ITEM_EVENT, itemEvent);
emitInBatch ( client , subMessage ) ;
}
world . setItemState ( itemEvent . itemId , itemEvent . state ) ;
} catch ( e ) {
console . error ( 'An error occurred on "item_event"' ) ;
console . error ( e ) ;
} * /
}
async handleReportMessage ( client : ExSocketInterface , reportPlayerMessage : ReportPlayerMessage ) {
try {
const reportedSocket = this . sockets . get ( reportPlayerMessage . getReporteduserid ( ) ) ;
if ( ! reportedSocket ) {
throw 'reported socket user not found' ;
}
//TODO report user on admin application
await adminApi . reportPlayer ( reportedSocket . userUuid , reportPlayerMessage . getReportcomment ( ) , client . userUuid )
} catch ( e ) {
console . error ( 'An error occurred on "handleReportMessage"' ) ;
console . error ( e ) ;
}
}
emitVideo ( socket : ExSocketInterface , data : WebRtcSignalToServerMessage ) : void {
const pusherToBackMessage = new PusherToBackMessage ( ) ;
pusherToBackMessage . setWebrtcsignaltoservermessage ( data ) ;
socket . backConnection . write ( pusherToBackMessage ) ;
//send only at user
/ * c o n s t c l i e n t = t h i s . s o c k e t s . g e t ( d a t a . g e t R e c e i v e r i d ( ) ) ;
if ( client === undefined ) {
console . warn ( "While exchanging a WebRTC signal: client with id " , data . getReceiverid ( ) , " does not exist. This might be a race condition." ) ;
return ;
}
const webrtcSignalToClient = new WebRtcSignalToClientMessage ( ) ;
webrtcSignalToClient . setUserid ( socket . userId ) ;
webrtcSignalToClient . setSignal ( data . getSignal ( ) ) ;
const serverToClientMessage = new ServerToClientMessage ( ) ;
serverToClientMessage . setWebrtcsignaltoclientmessage ( webrtcSignalToClient ) ;
if ( ! client . disconnecting ) {
client . send ( serverToClientMessage . serializeBinary ( ) . buffer , true ) ;
} * /
}
emitScreenSharing ( socket : ExSocketInterface , data : WebRtcSignalToServerMessage ) : void {
const pusherToBackMessage = new PusherToBackMessage ( ) ;
pusherToBackMessage . setWebrtcscreensharingsignaltoservermessage ( data ) ;
socket . backConnection . write ( pusherToBackMessage ) ;
//send only at user
/ * c o n s t c l i e n t = t h i s . s o c k e t s . g e t ( d a t a . g e t R e c e i v e r i d ( ) ) ;
if ( client === undefined ) {
console . warn ( "While exchanging a WEBRTC_SCREEN_SHARING signal: client with id " , data . getReceiverid ( ) , " does not exist. This might be a race condition." ) ;
return ;
}
const webrtcSignalToClient = new WebRtcSignalToClientMessage ( ) ;
webrtcSignalToClient . setUserid ( socket . userId ) ;
webrtcSignalToClient . setSignal ( data . getSignal ( ) ) ;
const serverToClientMessage = new ServerToClientMessage ( ) ;
serverToClientMessage . setWebrtcscreensharingsignaltoclientmessage ( webrtcSignalToClient ) ;
if ( ! client . disconnecting ) {
client . send ( serverToClientMessage . serializeBinary ( ) . buffer , true ) ;
} * /
}
private searchClientByIdOrFail ( userId : number ) : ExSocketInterface {
const client : ExSocketInterface | undefined = this . sockets . get ( userId ) ;
if ( client === undefined ) {
throw new Error ( "Could not find user with id " + userId ) ;
}
return client ;
}
leaveRoom ( socket : ExSocketInterface ) {
// leave previous room and world
try {
if ( socket . roomId ) {
try {
//user leaves room
const room : PusherRoom | undefined = this . Worlds . get ( socket . roomId ) ;
if ( room ) {
debug ( 'Leaving room %s.' , socket . roomId ) ;
room . leave ( socket ) ;
if ( room . isEmpty ( ) ) {
this . Worlds . delete ( socket . roomId ) ;
debug ( 'Room %s is empty. Deleting.' , socket . roomId ) ;
}
} else {
console . error ( 'Could not find the GameRoom the user is leaving!' ) ;
}
//user leave previous room
//Client.leave(Client.roomId);
} finally {
//delete Client.roomId;
this . sockets . delete ( socket . userId ) ;
clientEventsEmitter . emitClientLeave ( socket . userUuid , socket . roomId ) ;
console . log ( 'A user left (' , this . sockets . size , ' connected users)' ) ;
}
}
} finally {
if ( socket . backConnection ) {
socket . backConnection . end ( ) ;
}
}
}
async getOrCreateRoom ( roomId : string ) : Promise < PusherRoom > {
//check and create new world for a room
let world = this . Worlds . get ( roomId )
if ( world === undefined ) {
world = new PusherRoom (
roomId ,
this
/ * ( u s e r : U s e r , g r o u p : G r o u p ) = > t h i s . j o i n W e b R t c R o o m ( u s e r , g r o u p ) ,
( user : User , group : Group ) = > this . disConnectedUser ( user , group ) ,
MINIMUM_DISTANCE ,
GROUP_RADIUS ,
( thing : Movable , listener : User ) = > this . onRoomEnter ( thing , listener ) ,
( thing : Movable , position :PositionInterface , listener :User ) = > this . onClientMove ( thing , position , listener ) ,
( thing : Movable , listener :User ) = > this . onClientLeave ( thing , listener ) * /
) ;
if ( ! world . anonymous ) {
const data = await adminApi . fetchMapDetails ( world . organizationSlug , world . worldSlug , world . roomSlug )
world . tags = data . tags
world . policyType = Number ( data . policy_type )
}
this . Worlds . set ( roomId , world ) ;
}
return Promise . resolve ( world )
}
/ * p r i v a t e j o i n R o o m ( c l i e n t : E x S o c k e t I n t e r f a c e , p o s i t i o n : P o i n t I n t e r f a c e ) : P u s h e r R o o m {
const roomId = client . roomId ;
client . position = position ;
const world = this . Worlds . get ( roomId )
if ( world === undefined ) {
throw new Error ( 'Could not find room for ID: ' + client . roomId )
}
// Dispatch groups position to newly connected user
world . getGroups ( ) . forEach ( ( group : Group ) = > {
this . emitCreateUpdateGroupEvent ( client , group ) ;
} ) ;
//join world
world . join ( client , client . position ) ;
clientEventsEmitter . emitClientJoin ( client . userUuid , client . roomId ) ;
console . log ( new Date ( ) . toISOString ( ) + ' A user joined (' , this . sockets . size , ' connected users)' ) ;
return world ;
}
private onClientMove ( thing : Movable , position :PositionInterface , listener :User ) : void {
const clientListener = this . searchClientByIdOrFail ( listener . id ) ;
if ( thing instanceof User ) {
const clientUser = this . searchClientByIdOrFail ( thing . id ) ;
const userMovedMessage = new UserMovedMessage ( ) ;
userMovedMessage . setUserid ( clientUser . userId ) ;
userMovedMessage . setPosition ( ProtobufUtils . toPositionMessage ( clientUser . position ) ) ;
const subMessage = new SubMessage ( ) ;
subMessage . setUsermovedmessage ( userMovedMessage ) ;
clientListener . emitInBatch ( subMessage ) ;
//console.log("Sending USER_MOVED event");
} else if ( thing instanceof Group ) {
this . emitCreateUpdateGroupEvent ( clientListener , thing ) ;
} else {
console . error ( 'Unexpected type for Movable.' ) ;
}
}
private onClientLeave ( thing : Movable , listener :User ) {
const clientListener = this . searchClientByIdOrFail ( listener . id ) ;
if ( thing instanceof User ) {
const clientUser = this . searchClientByIdOrFail ( thing . id ) ;
this . emitUserLeftEvent ( clientListener , clientUser . userId ) ;
} else if ( thing instanceof Group ) {
this . emitDeleteGroupEvent ( clientListener , thing . getId ( ) ) ;
} else {
console . error ( 'Unexpected type for Movable.' ) ;
}
} * /
emitPlayGlobalMessage ( client : ExSocketInterface , playglobalmessage : PlayGlobalMessage ) {
const pusherToBackMessage = new PusherToBackMessage ( ) ;
pusherToBackMessage . setPlayglobalmessage ( playglobalmessage ) ;
client . backConnection . write ( pusherToBackMessage ) ;
}
public getWorlds ( ) : Map < string , PusherRoom > {
return this . Worlds ;
}
/ * *
*
* @param token
* /
searchClientByUuid ( uuid : string ) : ExSocketInterface | null {
for ( const socket of this . sockets . values ( ) ) {
if ( socket . userUuid === uuid ) {
return socket ;
}
}
return null ;
}
public handleQueryJitsiJwtMessage ( client : ExSocketInterface , queryJitsiJwtMessage : QueryJitsiJwtMessage ) {
const room = queryJitsiJwtMessage . getJitsiroom ( ) ;
const tag = queryJitsiJwtMessage . getTag ( ) ; // FIXME: this is not secure. We should load the JSON for the current room and check rights associated to room instead.
if ( SECRET_JITSI_KEY === '' ) {
throw new Error ( 'You must set the SECRET_JITSI_KEY key to the secret to generate JWT tokens for Jitsi.' ) ;
}
// Let's see if the current client has
const isAdmin = client . tags . includes ( tag ) ;
const jwt = Jwt . sign ( {
"aud" : "jitsi" ,
"iss" : JITSI_ISS ,
"sub" : JITSI_URL ,
"room" : room ,
"moderator" : isAdmin
} , SECRET_JITSI_KEY , {
expiresIn : '1d' ,
algorithm : "HS256" ,
header :
{
"alg" : "HS256" ,
"typ" : "JWT"
}
} ) ;
const sendJitsiJwtMessage = new SendJitsiJwtMessage ( ) ;
sendJitsiJwtMessage . setJitsiroom ( room ) ;
sendJitsiJwtMessage . setJwt ( jwt ) ;
const serverToClientMessage = new ServerToClientMessage ( ) ;
serverToClientMessage . setSendjitsijwtmessage ( sendJitsiJwtMessage ) ;
client . send ( serverToClientMessage . serializeBinary ( ) . buffer , true ) ;
}
2021-01-18 15:43:27 +01:00
public emitSendUserMessage ( userUuid : string , message : string , type : string ) : void {
2021-01-17 03:07:46 +01:00
const client = this . searchClientByUuid ( userUuid ) ;
if ( ! client ) {
throw Error ( 'client not found' ) ;
}
2020-12-11 12:23:50 +01:00
2021-01-17 03:07:46 +01:00
const adminMessage = new SendUserMessage ( ) ;
adminMessage . setMessage ( message ) ;
adminMessage . setType ( type ) ;
const pusherToBackMessage = new PusherToBackMessage ( ) ;
pusherToBackMessage . setSendusermessage ( adminMessage ) ;
client . backConnection . write ( pusherToBackMessage ) ;
2020-12-11 12:23:50 +01:00
2021-01-17 03:07:46 +01:00
/ * c o n s t b a c k C o n n e c t i o n = a w a i t a p i C l i e n t R e p o s i t o r y . g e t C l i e n t ( c l i e n t . r o o m I d ) ;
2020-12-11 12:23:50 +01:00
const adminMessage = new AdminMessage ( ) ;
adminMessage . setMessage ( message ) ;
2021-01-17 03:07:46 +01:00
adminMessage . setRoomid ( client . roomId ) ;
adminMessage . setRecipientuuid ( client . userUuid ) ;
2020-12-11 12:23:50 +01:00
backConnection . sendAdminMessage ( adminMessage , ( error ) = > {
if ( error !== null ) {
console . error ( 'Error while sending admin message' , error ) ;
}
2021-01-17 03:07:46 +01:00
} ) ; * /
2020-12-11 12:23:50 +01:00
}
2021-01-18 15:43:27 +01:00
public emitBan ( userUuid : string , message : string , type : string ) : void {
2021-01-17 03:07:46 +01:00
const client = this . searchClientByUuid ( userUuid ) ;
if ( ! client ) {
throw Error ( 'client not found' ) ;
}
2020-12-11 12:23:50 +01:00
2021-01-17 03:07:46 +01:00
const banUserMessage = new BanUserMessage ( ) ;
banUserMessage . setMessage ( message ) ;
banUserMessage . setType ( type ) ;
const pusherToBackMessage = new PusherToBackMessage ( ) ;
pusherToBackMessage . setBanusermessage ( banUserMessage ) ;
client . backConnection . write ( pusherToBackMessage ) ;
2020-12-11 12:23:50 +01:00
2021-01-17 03:07:46 +01:00
/ * c o n s t b a c k C o n n e c t i o n = a w a i t a p i C l i e n t R e p o s i t o r y . g e t C l i e n t ( c l i e n t . r o o m I d ) ;
const adminMessage = new AdminMessage ( ) ;
adminMessage . setMessage ( message ) ;
adminMessage . setRoomid ( client . roomId ) ;
adminMessage . setRecipientuuid ( client . userUuid ) ;
backConnection . sendAdminMessage ( adminMessage , ( error ) = > {
2020-12-11 12:23:50 +01:00
if ( error !== null ) {
2021-01-17 03:07:46 +01:00
console . error ( 'Error while sending admin message' , error ) ;
2020-12-11 12:23:50 +01:00
}
2021-01-17 03:07:46 +01:00
} ) ; * /
2020-11-13 18:00:22 +01:00
}
/ * *
* Merges the characterLayers received from the front ( as an array of string ) with the custom textures from the back .
* /
static mergeCharacterLayersAndCustomTextures ( characterLayers : string [ ] , memberTextures : CharacterTexture [ ] ) : CharacterLayer [ ] {
const characterLayerObjs : CharacterLayer [ ] = [ ] ;
for ( const characterLayer of characterLayers ) {
if ( characterLayer . startsWith ( 'customCharacterTexture' ) ) {
const customCharacterLayerId : number = + characterLayer . substr ( 22 ) ;
for ( const memberTexture of memberTextures ) {
if ( memberTexture . id == customCharacterLayerId ) {
characterLayerObjs . push ( {
name : characterLayer ,
url : memberTexture.url
} )
break ;
}
}
} else {
characterLayerObjs . push ( {
name : characterLayer ,
url : undefined
} )
}
}
return characterLayerObjs ;
}
public onUserEnters ( user : UserDescriptor , listener : ExSocketInterface ) : void {
const subMessage = new SubMessage ( ) ;
subMessage . setUserjoinedmessage ( user . toUserJoinedMessage ( ) ) ;
emitInBatch ( listener , subMessage ) ;
}
public onUserMoves ( user : UserDescriptor , listener : ExSocketInterface ) : void {
const subMessage = new SubMessage ( ) ;
subMessage . setUsermovedmessage ( user . toUserMovedMessage ( ) ) ;
emitInBatch ( listener , subMessage ) ;
}
public onUserLeaves ( userId : number , listener : ExSocketInterface ) : void {
const userLeftMessage = new UserLeftMessage ( ) ;
userLeftMessage . setUserid ( userId ) ;
const subMessage = new SubMessage ( ) ;
subMessage . setUserleftmessage ( userLeftMessage ) ;
emitInBatch ( listener , subMessage ) ;
}
public onGroupEnters ( group : GroupDescriptor , listener : ExSocketInterface ) : void {
const subMessage = new SubMessage ( ) ;
subMessage . setGroupupdatemessage ( group . toGroupUpdateMessage ( ) ) ;
emitInBatch ( listener , subMessage ) ;
}
public onGroupMoves ( group : GroupDescriptor , listener : ExSocketInterface ) : void {
this . onGroupEnters ( group , listener ) ;
}
public onGroupLeaves ( groupId : number , listener : ExSocketInterface ) : void {
const groupDeleteMessage = new GroupDeleteMessage ( ) ;
groupDeleteMessage . setGroupid ( groupId ) ;
const subMessage = new SubMessage ( ) ;
subMessage . setGroupdeletemessage ( groupDeleteMessage ) ;
emitInBatch ( listener , subMessage ) ;
}
}
export const socketManager = new SocketManager ( ) ;