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