Merge remote-tracking branch 'upstream/develop' into main
This commit is contained in:
commit
0e10a76eeb
@ -2,7 +2,7 @@ import {IRoomManagerServer} from "./Messages/generated/messages_grpc_pb";
|
||||
import {
|
||||
AdminGlobalMessage,
|
||||
AdminMessage,
|
||||
AdminPusherToBackMessage,
|
||||
AdminPusherToBackMessage,
|
||||
AdminRoomMessage,
|
||||
BanMessage,
|
||||
EmptyMessage,
|
||||
@ -15,7 +15,7 @@ import {
|
||||
ServerToClientMessage,
|
||||
SilentMessage,
|
||||
UserMovesMessage,
|
||||
WebRtcSignalToServerMessage,
|
||||
WebRtcSignalToServerMessage, WorldFullWarningToRoomMessage,
|
||||
ZoneMessage
|
||||
} from "./Messages/generated/messages_pb";
|
||||
import {sendUnaryData, ServerDuplexStream, ServerUnaryCall, ServerWritableStream} from "grpc";
|
||||
@ -184,6 +184,10 @@ const roomManager: IRoomManagerServer = {
|
||||
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};
|
||||
|
@ -24,6 +24,7 @@ import {
|
||||
UserJoinedZoneMessage,
|
||||
GroupUpdateZoneMessage,
|
||||
GroupLeftZoneMessage,
|
||||
WorldFullWarningMessage,
|
||||
UserLeftZoneMessage,
|
||||
BanUserMessage,
|
||||
} from "../Messages/generated/messages_pb";
|
||||
@ -58,6 +59,7 @@ function emitZoneMessage(subMessage: SubToPusherMessage, socket: ZoneSocket): vo
|
||||
// TODO: should we batch those every 100ms?
|
||||
const batchMessage = new BatchToPusherMessage();
|
||||
batchMessage.addPayload(subMessage);
|
||||
|
||||
|
||||
socket.write(batchMessage);
|
||||
}
|
||||
@ -298,20 +300,14 @@ export class SocketManager {
|
||||
|
||||
const roomId = joinRoomMessage.getRoomid();
|
||||
|
||||
const world = await socketManager.getOrCreateRoom(roomId);
|
||||
|
||||
// Dispatch groups position to newly connected user
|
||||
/*world.getGroups().forEach((group: Group) => {
|
||||
this.emitCreateUpdateGroupEvent(socket, group);
|
||||
});*/
|
||||
const room = await socketManager.getOrCreateRoom(roomId);
|
||||
|
||||
//join world
|
||||
const user = world.join(socket, joinRoomMessage);
|
||||
const user = room.join(socket, joinRoomMessage);
|
||||
|
||||
clientEventsEmitter.emitClientJoin(user.uuid, roomId);
|
||||
//console.log(new Date().toISOString() + ' A user joined (', this.sockets.size, ' connected users)');
|
||||
console.log(new Date().toISOString() + ' A user joined');
|
||||
return {room: world, user};
|
||||
return {room, user};
|
||||
}
|
||||
|
||||
private onZoneEnter(thing: Movable, fromZone: Zone|null, listener: ZoneSocket) {
|
||||
@ -758,6 +754,24 @@ export class SocketManager {
|
||||
recipient.socket.write(clientMessage);
|
||||
});
|
||||
}
|
||||
|
||||
dispatchWorlFullWarning(roomId: string,): void {
|
||||
const room = this.rooms.get(roomId);
|
||||
if (!room) {
|
||||
//todo: this should cause the http call to return a 500
|
||||
console.error("In sendAdminRoomMessage, could not find room with id '" + roomId + "'. Maybe the room was closed a few milliseconds ago and there was a race condition?");
|
||||
return;
|
||||
}
|
||||
|
||||
room.getUsers().forEach((recipient) => {
|
||||
const worldFullMessage = new WorldFullWarningMessage();
|
||||
|
||||
const clientMessage = new ServerToClientMessage();
|
||||
clientMessage.setWorldfullwarningmessage(worldFullMessage);
|
||||
|
||||
recipient.socket.write(clientMessage);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const socketManager = new SocketManager();
|
||||
|
18
front/dist/resources/html/warningContainer.html
vendored
Normal file
18
front/dist/resources/html/warningContainer.html
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<style>
|
||||
#warningMain {
|
||||
border-radius: 5px;
|
||||
height: 100px;
|
||||
width: 300px;
|
||||
background-color: red;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#warningMain h2 {
|
||||
padding: 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<main id="warningMain">
|
||||
<h2>Warning!</h2>
|
||||
<p>This world is close to its limit!</p>
|
||||
</main>
|
@ -7,21 +7,15 @@ import {localUserStore} from "./LocalUserStore";
|
||||
import {LocalUser} from "./LocalUser";
|
||||
import {Room} from "./Room";
|
||||
import {Subject} from "rxjs";
|
||||
import {ServerToClientMessage} from "../Messages/generated/messages_pb";
|
||||
|
||||
export enum ConnexionMessageEventTypes {
|
||||
worldFull = 1,
|
||||
}
|
||||
|
||||
export interface ConnexionMessageEvent {
|
||||
type: ConnexionMessageEventTypes,
|
||||
}
|
||||
|
||||
class ConnectionManager {
|
||||
private localUser!:LocalUser;
|
||||
|
||||
private connexionType?: GameConnexionTypes
|
||||
|
||||
public _connexionMessageStream:Subject<ConnexionMessageEvent> = new Subject();
|
||||
public _serverToClientMessageStream:Subject<ServerToClientMessage> = new Subject();
|
||||
/**
|
||||
* Tries to login to the node server and return the starting map url to be loaded
|
||||
*/
|
||||
|
@ -8,6 +8,7 @@ const gameQualityKey = 'gameQuality';
|
||||
const videoQualityKey = 'videoQuality';
|
||||
const audioPlayerVolumeKey = 'audioVolume';
|
||||
const audioPlayerMuteKey = 'audioMute';
|
||||
const helpCameraSettingsShown = 'helpCameraSettingsShown';
|
||||
|
||||
class LocalUserStore {
|
||||
saveUser(localUser: LocalUser) {
|
||||
@ -73,6 +74,13 @@ class LocalUserStore {
|
||||
getAudioPlayerMuted(): boolean {
|
||||
return localStorage.getItem(audioPlayerMuteKey) === 'true';
|
||||
}
|
||||
|
||||
setHelpCameraSettingsShown(): void {
|
||||
localStorage.setItem(helpCameraSettingsShown, '1');
|
||||
}
|
||||
getHelpCameraSettingsShown(): boolean {
|
||||
return localStorage.getItem(helpCameraSettingsShown) === '1';
|
||||
}
|
||||
}
|
||||
|
||||
export const localUserStore = new LocalUserStore();
|
||||
|
@ -43,7 +43,8 @@ import {
|
||||
} from "./ConnexionModels";
|
||||
import {BodyResourceDescriptionInterface} from "../Phaser/Entity/PlayerTextures";
|
||||
import {adminMessagesService} from "./AdminMessagesService";
|
||||
import {connectionManager, ConnexionMessageEventTypes} from "./ConnectionManager";
|
||||
import {worldFullMessageStream} from "./WorldFullMessageStream";
|
||||
import {worldFullWarningStream} from "./WorldFullWarningStream";
|
||||
|
||||
const manualPingDelay = 20000;
|
||||
|
||||
@ -156,8 +157,8 @@ export class RoomConnection implements RoomConnection {
|
||||
items
|
||||
} as RoomJoinedMessageInterface
|
||||
});
|
||||
} else if (message.hasErrormessage()) {
|
||||
connectionManager._connexionMessageStream.next({type: ConnexionMessageEventTypes.worldFull}); //todo: generalize this behavior to all messages
|
||||
} else if (message.hasWorldfullmessage()) {
|
||||
worldFullMessageStream.onMessage();
|
||||
this.closed = true;
|
||||
} else if (message.hasWebrtcsignaltoclientmessage()) {
|
||||
this.dispatch(EventMessage.WEBRTC_SIGNAL, message.getWebrtcsignaltoclientmessage());
|
||||
@ -179,6 +180,8 @@ export class RoomConnection implements RoomConnection {
|
||||
adminMessagesService.onSendusermessage(message.getSendusermessage() as SendUserMessage);
|
||||
} else if (message.hasBanusermessage()) {
|
||||
adminMessagesService.onSendusermessage(message.getSendusermessage() as BanUserMessage);
|
||||
} else if (message.hasWorldfullwarningmessage()) {
|
||||
worldFullWarningStream.onMessage();
|
||||
} else {
|
||||
throw new Error('Unknown message received');
|
||||
}
|
||||
|
14
front/src/Connexion/WorldFullMessageStream.ts
Normal file
14
front/src/Connexion/WorldFullMessageStream.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import {Subject} from "rxjs";
|
||||
|
||||
class WorldFullMessageStream {
|
||||
|
||||
private _stream:Subject<void> = new Subject();
|
||||
public stream = this._stream.asObservable();
|
||||
|
||||
|
||||
onMessage() {
|
||||
this._stream.next();
|
||||
}
|
||||
}
|
||||
|
||||
export const worldFullMessageStream = new WorldFullMessageStream();
|
14
front/src/Connexion/WorldFullWarningStream.ts
Normal file
14
front/src/Connexion/WorldFullWarningStream.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import {Subject} from "rxjs";
|
||||
|
||||
class WorldFullWarningStream {
|
||||
|
||||
private _stream:Subject<void> = new Subject();
|
||||
public stream = this._stream.asObservable();
|
||||
|
||||
|
||||
onMessage() {
|
||||
this._stream.next();
|
||||
}
|
||||
}
|
||||
|
||||
export const worldFullWarningStream = new WorldFullWarningStream();
|
14
front/src/Phaser/Components/WarningContainer.ts
Normal file
14
front/src/Phaser/Components/WarningContainer.ts
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
export const warningContainerKey = 'warningContainer';
|
||||
export const warningContainerHtml = 'resources/html/warningContainer.html';
|
||||
|
||||
export class WarningContainer extends Phaser.GameObjects.DOMElement {
|
||||
|
||||
constructor(scene: Phaser.Scene) {
|
||||
super(scene, 100, 0);
|
||||
this.setOrigin(0, 0);
|
||||
this.createFromCache(warningContainerKey);
|
||||
this.scene.add.existing(this);
|
||||
}
|
||||
|
||||
}
|
@ -86,7 +86,10 @@ export class GameManager {
|
||||
console.log('starting '+ (this.currentGameSceneName || this.startRoom.id))
|
||||
scenePlugin.start(this.currentGameSceneName || this.startRoom.id);
|
||||
scenePlugin.launch(MenuSceneName);
|
||||
scenePlugin.launch(HelpCameraSettingsSceneName);//700
|
||||
|
||||
if (!localUserStore.getHelpCameraSettingsShown()) {
|
||||
scenePlugin.launch(HelpCameraSettingsSceneName);//700
|
||||
}
|
||||
}
|
||||
|
||||
public gameSceneIsCreated(scene: GameScene) {
|
||||
|
@ -41,7 +41,7 @@ import {ActionableItem} from "../Items/ActionableItem";
|
||||
import {UserInputManager} from "../UserInput/UserInputManager";
|
||||
import {UserMovedMessage} from "../../Messages/generated/messages_pb";
|
||||
import {ProtobufClientUtils} from "../../Network/ProtobufClientUtils";
|
||||
import {connectionManager, ConnexionMessageEvent, ConnexionMessageEventTypes} from "../../Connexion/ConnectionManager";
|
||||
import {connectionManager} from "../../Connexion/ConnectionManager";
|
||||
import {RoomConnection} from "../../Connexion/RoomConnection";
|
||||
import {GlobalMessageManager} from "../../Administration/GlobalMessageManager";
|
||||
import {userMessageManager} from "../../Administration/UserMessageManager";
|
||||
@ -65,6 +65,7 @@ import CanvasTexture = Phaser.Textures.CanvasTexture;
|
||||
import GameObject = Phaser.GameObjects.GameObject;
|
||||
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
|
||||
import {Subscription} from "rxjs";
|
||||
import {worldFullMessageStream} from "../../Connexion/WorldFullMessageStream";
|
||||
|
||||
export interface GameSceneInitInterface {
|
||||
initPosition: PointInterface|null,
|
||||
@ -306,7 +307,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
urlManager.pushRoomIdToUrl(this.room);
|
||||
this.startLayerName = urlManager.getStartLayerNameFromUrl();
|
||||
|
||||
this.messageSubscription = connectionManager._connexionMessageStream.subscribe((event) => this.onConnexionMessage(event))
|
||||
this.messageSubscription = worldFullMessageStream.stream.subscribe((message) => this.showWorldFullError())
|
||||
|
||||
const playerName = gameManager.getPlayerName();
|
||||
if (!playerName) {
|
||||
@ -1230,7 +1231,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
mediaManager.removeTriggerCloseJitsiFrameButton('close-jisi');
|
||||
}
|
||||
|
||||
//todo: into onConnexionMessage
|
||||
//todo: put this into an 'orchestrator' scene (EntryScene?)
|
||||
private bannedUser(){
|
||||
this.cleanupClosingScene();
|
||||
this.userInputManager.clearAllKeys();
|
||||
@ -1241,16 +1242,15 @@ export class GameScene extends ResizableScene implements CenterListener {
|
||||
});
|
||||
}
|
||||
|
||||
private onConnexionMessage(event: ConnexionMessageEvent) {
|
||||
if (event.type === ConnexionMessageEventTypes.worldFull) {
|
||||
this.cleanupClosingScene();
|
||||
this.scene.stop(ReconnectingSceneName);
|
||||
this.userInputManager.clearAllKeys();
|
||||
this.scene.start(ErrorSceneName, {
|
||||
title: 'Connection rejected',
|
||||
subTitle: 'The world you are trying to join is full. Try again later.',
|
||||
message: 'If you want more information, you may contact us at: workadventure@thecodingmachine.com'
|
||||
});
|
||||
}
|
||||
//todo: put this into an 'orchestrator' scene (EntryScene?)
|
||||
private showWorldFullError(): void {
|
||||
this.cleanupClosingScene();
|
||||
this.scene.stop(ReconnectingSceneName);
|
||||
this.userInputManager.clearAllKeys();
|
||||
this.scene.start(ErrorSceneName, {
|
||||
title: 'Connection rejected',
|
||||
subTitle: 'The world you are trying to join is full. Try again later.',
|
||||
message: 'If you want more information, you may contact us at: workadventure@thecodingmachine.com'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -61,26 +61,22 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
this.microphoneNameField = new TextField(this, this.game.renderer.width / 2, this.game.renderer.height - 40, '');
|
||||
|
||||
this.arrowRight = new Image(this, 0, 0, LoginTextures.arrowRight);
|
||||
this.arrowRight.setOrigin(0.5, 0.5);
|
||||
this.arrowRight.setVisible(false);
|
||||
this.arrowRight.setInteractive().on('pointerdown', this.nextCam.bind(this));
|
||||
this.add.existing(this.arrowRight);
|
||||
|
||||
this.arrowLeft = new Image(this, 0, 0, LoginTextures.arrowRight);
|
||||
this.arrowLeft.setOrigin(0.5, 0.5);
|
||||
this.arrowLeft.setVisible(false);
|
||||
this.arrowLeft.flipX = true;
|
||||
this.arrowLeft.setInteractive().on('pointerdown', this.previousCam.bind(this));
|
||||
this.add.existing(this.arrowLeft);
|
||||
|
||||
this.arrowUp = new Image(this, 0, 0, LoginTextures.arrowUp);
|
||||
this.arrowUp.setOrigin(0.5, 0.5);
|
||||
this.arrowUp.setVisible(false);
|
||||
this.arrowUp.setInteractive().on('pointerdown', this.previousMic.bind(this));
|
||||
this.add.existing(this.arrowUp);
|
||||
|
||||
this.arrowDown = new Image(this, 0, 0, LoginTextures.arrowUp);
|
||||
this.arrowDown.setOrigin(0.5, 0.5);
|
||||
this.arrowDown.setVisible(false);
|
||||
this.arrowDown.flipY = true;
|
||||
this.arrowDown.setInteractive().on('pointerdown', this.nextMic.bind(this));
|
||||
@ -164,8 +160,6 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
|
||||
private updateWebCamName(): void {
|
||||
if (this.camerasList.length > 1) {
|
||||
const div = HtmlUtils.getElementByIdOrFail<HTMLVideoElement>('myCamVideoSetup');
|
||||
|
||||
let label = this.camerasList[this.cameraSelected].label;
|
||||
// remove text in parenthesis
|
||||
label = label.replace(/\([^()]*\)/g, '').trim();
|
||||
@ -173,17 +167,8 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
label = label.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
||||
this.cameraNameField.text = label;
|
||||
|
||||
if (this.cameraSelected < this.camerasList.length - 1) {
|
||||
this.arrowRight.setVisible(true);
|
||||
} else {
|
||||
this.arrowRight.setVisible(false);
|
||||
}
|
||||
|
||||
if (this.cameraSelected > 0) {
|
||||
this.arrowLeft.setVisible(true);
|
||||
} else {
|
||||
this.arrowLeft.setVisible(false);
|
||||
}
|
||||
this.arrowRight.setVisible(this.cameraSelected < this.camerasList.length - 1);
|
||||
this.arrowLeft.setVisible(this.cameraSelected > 0);
|
||||
}
|
||||
if (this.microphonesList.length > 1) {
|
||||
let label = this.microphonesList[this.microphoneSelected].label;
|
||||
@ -194,17 +179,8 @@ export class EnableCameraScene extends Phaser.Scene {
|
||||
|
||||
this.microphoneNameField.text = label;
|
||||
|
||||
if (this.microphoneSelected < this.microphonesList.length - 1) {
|
||||
this.arrowDown.setVisible(true);
|
||||
} else {
|
||||
this.arrowDown.setVisible(false);
|
||||
}
|
||||
|
||||
if (this.microphoneSelected > 0) {
|
||||
this.arrowUp.setVisible(true);
|
||||
} else {
|
||||
this.arrowUp.setVisible(false);
|
||||
}
|
||||
this.arrowDown.setVisible(this.microphoneSelected < this.microphonesList.length - 1);
|
||||
this.arrowUp.setVisible(this.microphoneSelected > 0);
|
||||
|
||||
}
|
||||
this.reposition();
|
||||
|
@ -1,5 +1,6 @@
|
||||
import {mediaManager} from "../../WebRtc/MediaManager";
|
||||
import {HtmlUtils} from "../../WebRtc/HtmlUtils";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
|
||||
export const HelpCameraSettingsSceneName = 'HelpCameraSettingsScene';
|
||||
const helpCameraSettings = 'helpCameraSettings';
|
||||
@ -19,6 +20,7 @@ export class HelpCameraSettingsScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
create(){
|
||||
localUserStore.setHelpCameraSettingsShown();
|
||||
this.createHelpCameraSettings();
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,8 @@ import {mediaManager} from "../../WebRtc/MediaManager";
|
||||
import {gameReportKey, gameReportRessource, ReportMenu} from "./ReportMenu";
|
||||
import {connectionManager} from "../../Connexion/ConnectionManager";
|
||||
import {GameConnexionTypes} from "../../Url/UrlManager";
|
||||
import {WarningContainer, warningContainerHtml, warningContainerKey} from "../Components/WarningContainer";
|
||||
import {worldFullWarningStream} from "../../Connexion/WorldFullWarningStream";
|
||||
|
||||
export const MenuSceneName = 'MenuScene';
|
||||
const gameMenuKey = 'gameMenu';
|
||||
@ -30,6 +32,8 @@ export class MenuScene extends Phaser.Scene {
|
||||
private gameQualityValue: number;
|
||||
private videoQualityValue: number;
|
||||
private menuButton!: Phaser.GameObjects.DOMElement;
|
||||
private warningContainer: WarningContainer | null = null;
|
||||
private warningContainerTimeout: NodeJS.Timeout | null = null;
|
||||
|
||||
constructor() {
|
||||
super({key: MenuSceneName});
|
||||
@ -44,6 +48,7 @@ export class MenuScene extends Phaser.Scene {
|
||||
this.load.html(gameSettingsMenuKey, 'resources/html/gameQualityMenu.html');
|
||||
this.load.html(gameShare, 'resources/html/gameShare.html');
|
||||
this.load.html(gameReportKey, gameReportRessource);
|
||||
this.load.html(warningContainerKey, warningContainerHtml);
|
||||
}
|
||||
|
||||
create() {
|
||||
@ -85,6 +90,8 @@ export class MenuScene extends Phaser.Scene {
|
||||
|
||||
this.menuElement.addListener('click');
|
||||
this.menuElement.on('click', this.onMenuClick.bind(this));
|
||||
|
||||
worldFullWarningStream.stream.subscribe(() => this.showWorldCapacityWarning());
|
||||
}
|
||||
|
||||
//todo put this method in a parent menuElement class
|
||||
@ -121,6 +128,21 @@ export class MenuScene extends Phaser.Scene {
|
||||
ease: 'Power3'
|
||||
});
|
||||
}
|
||||
|
||||
private showWorldCapacityWarning() {
|
||||
if (!this.warningContainer) {
|
||||
this.warningContainer = new WarningContainer(this);
|
||||
}
|
||||
if (this.warningContainerTimeout) {
|
||||
clearTimeout(this.warningContainerTimeout);
|
||||
}
|
||||
this.warningContainerTimeout = setTimeout(() => {
|
||||
this.warningContainer?.destroy();
|
||||
this.warningContainer = null
|
||||
this.warningContainerTimeout = null
|
||||
}, 2000);
|
||||
|
||||
}
|
||||
|
||||
private closeSideMenu(): void {
|
||||
if (!this.sideMenuOpened) return;
|
||||
|
@ -53,7 +53,7 @@ class CoWebsiteManager {
|
||||
}
|
||||
|
||||
get isFullScreen(): boolean {
|
||||
return this.verticalMode ? this.height === this.cowebsiteDiv.clientHeight : this.width === this.cowebsiteDiv.clientWidth
|
||||
return this.verticalMode ? this.height === window.innerHeight : this.width === window.innerWidth;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
@ -199,6 +199,7 @@ class CoWebsiteManager {
|
||||
private fullscreen(): void {
|
||||
if (this.isFullScreen) {
|
||||
this.resetStyle();
|
||||
this.fire();
|
||||
//we don't trigger a resize of the phaser game since it won't be visible anyway.
|
||||
HtmlUtils.getElementByIdOrFail(cowebsiteOpenFullScreenImageId).style.display = 'inline';
|
||||
HtmlUtils.getElementByIdOrFail(cowebsiteCloseFullScreenImageId).style.display = 'none';
|
||||
|
@ -197,6 +197,15 @@ message SendUserMessage{
|
||||
string message = 2;
|
||||
}
|
||||
|
||||
message WorldFullWarningMessage{
|
||||
}
|
||||
message WorldFullWarningToRoomMessage{
|
||||
string roomId = 1;
|
||||
}
|
||||
|
||||
message WorldFullMessage{
|
||||
}
|
||||
|
||||
message BanUserMessage{
|
||||
string type = 1;
|
||||
string message = 2;
|
||||
@ -218,6 +227,8 @@ message ServerToClientMessage {
|
||||
SendUserMessage sendUserMessage = 12;
|
||||
BanUserMessage banUserMessage = 13;
|
||||
AdminRoomMessage adminRoomMessage = 14;
|
||||
WorldFullWarningMessage worldFullWarningMessage = 15;
|
||||
WorldFullMessage worldFullMessage = 16;
|
||||
}
|
||||
}
|
||||
|
||||
@ -383,4 +394,5 @@ service RoomManager {
|
||||
rpc sendGlobalAdminMessage(AdminGlobalMessage) returns (EmptyMessage);
|
||||
rpc ban(BanMessage) returns (EmptyMessage);
|
||||
rpc sendAdminMessageToRoom(AdminRoomMessage) returns (EmptyMessage);
|
||||
rpc sendWorldFullWarningToRoom(WorldFullWarningToRoomMessage) returns (EmptyMessage);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import {BaseController} from "./BaseController";
|
||||
import {HttpRequest, HttpResponse, TemplatedApp} from "uWebSockets.js";
|
||||
import {ADMIN_API_TOKEN} from "../Enum/EnvironmentVariable";
|
||||
import {apiClientRepository} from "../Services/ApiClientRepository";
|
||||
import {AdminRoomMessage} from "../Messages/generated/messages_pb";
|
||||
import {AdminRoomMessage, WorldFullWarningToRoomMessage} from "../Messages/generated/messages_pb";
|
||||
|
||||
|
||||
export class AdminController extends BaseController{
|
||||
@ -40,22 +40,36 @@ export class AdminController extends BaseController{
|
||||
if (typeof body.text !== 'string') {
|
||||
throw 'Incorrect text parameter'
|
||||
}
|
||||
if (body.type !== 'capacity' && body.type !== 'message') {
|
||||
throw 'Incorrect type parameter'
|
||||
}
|
||||
if (!body.targets || typeof body.targets !== 'object') {
|
||||
throw 'Incorrect targets parameter'
|
||||
}
|
||||
const text: string = body.text;
|
||||
const type: string = body.type;
|
||||
const targets: string[] = body.targets;
|
||||
|
||||
await Promise.all(targets.map((roomId) => {
|
||||
return apiClientRepository.getClient(roomId).then((roomClient) =>{
|
||||
return new Promise((res, rej) => {
|
||||
const roomMessage = new AdminRoomMessage();
|
||||
roomMessage.setMessage(text);
|
||||
roomMessage.setRoomid(roomId);
|
||||
|
||||
roomClient.sendAdminMessageToRoom(roomMessage, (err) => {
|
||||
err ? rej(err) : res();
|
||||
});
|
||||
if (type === 'message') {
|
||||
const roomMessage = new AdminRoomMessage();
|
||||
roomMessage.setMessage(text);
|
||||
roomMessage.setRoomid(roomId);
|
||||
|
||||
roomClient.sendAdminMessageToRoom(roomMessage, (err) => {
|
||||
err ? rej(err) : res();
|
||||
});
|
||||
} else if (type === 'capacity') {
|
||||
const roomMessage = new WorldFullWarningToRoomMessage();
|
||||
roomMessage.setRoomid(roomId);
|
||||
|
||||
roomClient.sendWorldFullWarningToRoom(roomMessage, (err) => {
|
||||
err ? rej(err) : res();
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
@ -258,12 +258,12 @@ export class IoSocketController {
|
||||
/* Handlers */
|
||||
open: (ws) => {
|
||||
if(ws.rejected === true) {
|
||||
emitError(ws, 'World is full');
|
||||
socketManager.emitWorldFullMessage(ws);
|
||||
ws.close();
|
||||
}
|
||||
|
||||
// Let's join the room
|
||||
const client = this.initClient(ws); //todo: into the upgrade instead?
|
||||
const client = this.initClient(ws);
|
||||
socketManager.handleJoinRoom(client);
|
||||
|
||||
//get data information and show messages
|
||||
|
@ -19,15 +19,15 @@ import {
|
||||
JoinRoomMessage,
|
||||
CharacterLayerMessage,
|
||||
PusherToBackMessage,
|
||||
WorldFullMessage,
|
||||
AdminPusherToBackMessage,
|
||||
ServerToAdminClientMessage,
|
||||
SendUserMessage,
|
||||
BanUserMessage, UserJoinedRoomMessage, UserLeftRoomMessage, AdminMessage, BanMessage
|
||||
UserJoinedRoomMessage, UserLeftRoomMessage, AdminMessage, BanMessage
|
||||
} from "../Messages/generated/messages_pb";
|
||||
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
|
||||
import {JITSI_ISS, SECRET_JITSI_KEY} from "../Enum/EnvironmentVariable";
|
||||
import {adminApi, CharacterTexture} from "./AdminApi";
|
||||
import {emitError, emitInBatch} from "./IoSocketHelpers";
|
||||
import {emitInBatch} from "./IoSocketHelpers";
|
||||
import Jwt from "jsonwebtoken";
|
||||
import {JITSI_URL} from "../Enum/EnvironmentVariable";
|
||||
import {clientEventsEmitter} from "./ClientEventsEmitter";
|
||||
@ -36,6 +36,7 @@ import {apiClientRepository} from "./ApiClientRepository";
|
||||
import {GroupDescriptor, UserDescriptor, ZoneEventListener} from "_Model/Zone";
|
||||
import Debug from "debug";
|
||||
import {ExAdminSocketInterface} from "_Model/Websocket/ExAdminSocketInterface";
|
||||
import {WebSocket} from "uWebSockets.js";
|
||||
|
||||
const debug = Debug('socket');
|
||||
|
||||
@ -52,6 +53,7 @@ export interface AdminSocketData {
|
||||
}
|
||||
|
||||
export class SocketManager implements ZoneEventListener {
|
||||
|
||||
private Worlds: Map<string, PusherRoom> = new Map<string, PusherRoom>();
|
||||
private sockets: Map<number, ExSocketInterface> = new Map<number, ExSocketInterface>();
|
||||
|
||||
@ -533,6 +535,15 @@ export class SocketManager implements ZoneEventListener {
|
||||
|
||||
emitInBatch(listener, subMessage);
|
||||
}
|
||||
|
||||
public emitWorldFullMessage(client: WebSocket) {
|
||||
const errorMessage = new WorldFullMessage();
|
||||
|
||||
const serverToClientMessage = new ServerToClientMessage();
|
||||
serverToClientMessage.setWorldfullmessage(errorMessage);
|
||||
|
||||
client.send(serverToClientMessage.serializeBinary().buffer, true);
|
||||
}
|
||||
}
|
||||
|
||||
export const socketManager = new SocketManager();
|
||||
|
Loading…
Reference in New Issue
Block a user