workadventure/back/src/RoomManager.ts

194 lines
8.1 KiB
TypeScript

import {IRoomManagerServer} from "./Messages/generated/messages_grpc_pb";
import {
AdminGlobalMessage,
AdminMessage,
AdminPusherToBackMessage,
AdminRoomMessage,
BanMessage,
EmptyMessage,
ItemEventMessage,
JoinRoomMessage,
PlayGlobalMessage,
PusherToBackMessage,
QueryJitsiJwtMessage,
ServerToAdminClientMessage,
ServerToClientMessage,
SilentMessage,
UserMovesMessage,
WebRtcSignalToServerMessage, WorldFullWarningToRoomMessage,
ZoneMessage
} from "./Messages/generated/messages_pb";
import {sendUnaryData, ServerDuplexStream, ServerUnaryCall, ServerWritableStream} from "grpc";
import {socketManager} from "./Services/SocketManager";
import {emitError} from "./Services/MessageHelpers";
import {User, UserSocket} from "./Model/User";
import {GameRoom} from "./Model/GameRoom";
import Debug from "debug";
import {Admin} from "./Model/Admin";
const debug = Debug('roommanager');
export type AdminSocket = ServerDuplexStream<AdminPusherToBackMessage, ServerToAdminClientMessage>;
export type ZoneSocket = ServerWritableStream<ZoneMessage, ServerToClientMessage>;
const roomManager: IRoomManagerServer = {
joinRoom: (call: UserSocket): void => {
console.log('joinRoom called');
let room: GameRoom|null = null;
let user: User|null = null;
call.on('data', (message: PusherToBackMessage) => {
try {
if (room === null || user === null) {
if (message.hasJoinroommessage()) {
socketManager.handleJoinRoom(call, message.getJoinroommessage() as JoinRoomMessage).then(({room: gameRoom, user: myUser}) => {
room = gameRoom;
user = myUser;
});
} else {
throw new Error('The first message sent MUST be of type JoinRoomMessage');
}
} else {
if (message.hasJoinroommessage()) {
throw new Error('Cannot call JoinRoomMessage twice!');
} else if (message.hasUsermovesmessage()) {
socketManager.handleUserMovesMessage(room, user, message.getUsermovesmessage() as UserMovesMessage);
} else if (message.hasSilentmessage()) {
socketManager.handleSilentMessage(room, user, message.getSilentmessage() as SilentMessage);
} else if (message.hasItemeventmessage()) {
socketManager.handleItemEvent(room, user, message.getItemeventmessage() as ItemEventMessage);
} else if (message.hasWebrtcsignaltoservermessage()) {
socketManager.emitVideo(room, user, message.getWebrtcsignaltoservermessage() as WebRtcSignalToServerMessage);
} else if (message.hasWebrtcscreensharingsignaltoservermessage()) {
socketManager.emitScreenSharing(room, user, message.getWebrtcscreensharingsignaltoservermessage() as WebRtcSignalToServerMessage);
} else if (message.hasPlayglobalmessage()) {
socketManager.emitPlayGlobalMessage(room, message.getPlayglobalmessage() as PlayGlobalMessage);
} else if (message.hasQueryjitsijwtmessage()){
socketManager.handleQueryJitsiJwtMessage(user, message.getQueryjitsijwtmessage() as QueryJitsiJwtMessage);
}else if (message.hasSendusermessage()) {
const sendUserMessage = message.getSendusermessage();
if(sendUserMessage !== undefined) {
socketManager.handlerSendUserMessage(user, sendUserMessage);
}
}else if (message.hasBanusermessage()) {
const banUserMessage = message.getBanusermessage();
if(banUserMessage !== undefined) {
socketManager.handlerBanUserMessage(room, user, banUserMessage);
}
} else {
throw new Error('Unhandled message type');
}
}
} catch (e) {
emitError(call, e);
call.end();
}
});
call.on('end', () => {
debug('joinRoom ended');
if (user !== null && room !== null) {
socketManager.leaveRoom(room, user);
}
call.end();
room = null;
user = null;
});
call.on('error', (err: Error) => {
console.error('An error occurred in joinRoom stream:', err);
});
},
listenZone(call: ZoneSocket): void {
debug('listenZone called');
const zoneMessage = call.request;
socketManager.addZoneListener(call, zoneMessage.getRoomid(), zoneMessage.getX(), zoneMessage.getY());
call.on('cancelled', () => {
debug('listenZone cancelled');
socketManager.removeZoneListener(call, zoneMessage.getRoomid(), zoneMessage.getX(), zoneMessage.getY());
call.end();
})
call.on('close', () => {
debug('listenZone connection closed');
socketManager.removeZoneListener(call, zoneMessage.getRoomid(), zoneMessage.getX(), zoneMessage.getY());
}).on('error', (e) => {
console.error('An error occurred in listenZone stream:', e);
socketManager.removeZoneListener(call, zoneMessage.getRoomid(), zoneMessage.getX(), zoneMessage.getY());
call.end();
});
},
adminRoom(call: AdminSocket): void {
console.log('adminRoom called');
const admin = new Admin(call);
let room: GameRoom|null = null;
call.on('data', (message: AdminPusherToBackMessage) => {
try {
if (room === null) {
if (message.hasSubscribetoroom()) {
const roomId = message.getSubscribetoroom();
socketManager.handleJoinAdminRoom(admin, roomId).then((gameRoom: GameRoom) => {
room = gameRoom;
});
} else {
throw new Error('The first message sent MUST be of type JoinRoomMessage');
}
}
} catch (e) {
emitError(call, e);
call.end();
}
});
call.on('end', () => {
debug('joinRoom ended');
if (room !== null) {
socketManager.leaveAdminRoom(room, admin);
}
call.end();
room = null;
});
call.on('error', (err: Error) => {
console.error('An error occurred in joinAdminRoom stream:', err);
});
},
sendAdminMessage(call: ServerUnaryCall<AdminMessage>, callback: sendUnaryData<EmptyMessage>): void {
socketManager.sendAdminMessage(call.request.getRoomid(), call.request.getRecipientuuid(), call.request.getMessage());
callback(null, new EmptyMessage());
},
sendGlobalAdminMessage(call: ServerUnaryCall<AdminGlobalMessage>, callback: sendUnaryData<EmptyMessage>): void {
throw new Error('Not implemented yet');
// TODO
callback(null, new EmptyMessage());
},
ban(call: ServerUnaryCall<BanMessage>, callback: sendUnaryData<EmptyMessage>): void {
// FIXME Work in progress
socketManager.banUser(call.request.getRoomid(), call.request.getRecipientuuid(), call.request.getMessage());
callback(null, new EmptyMessage());
},
sendAdminMessageToRoom(call: ServerUnaryCall<AdminRoomMessage>, callback: sendUnaryData<EmptyMessage>): void {
socketManager.sendAdminRoomMessage(call.request.getRoomid(), call.request.getMessage());
callback(null, new EmptyMessage());
},
sendWorldFullWarningToRoom(call: ServerUnaryCall<WorldFullWarningToRoomMessage>, callback: sendUnaryData<EmptyMessage>): void {
socketManager.dispatchWorlFullWarning(call.request.getRoomid());
callback(null, new EmptyMessage());
},
};
export {roomManager};