Merge pull request #793 from thecodingmachine/adminWorldsLimit

FEATURE: the connexion error an user can get when a world is full is now correctly treated.
This commit is contained in:
Kharhamel 2021-03-09 17:45:43 +01:00 committed by GitHub
commit 21cc842c33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 127 additions and 215 deletions

View file

@ -77,8 +77,10 @@ export class TypeMessageExt implements TypeMessageInterface{
}
}
}
export class Ban extends TypeMessageExt {
}
export class Message extends TypeMessageExt {}
export class Ban extends TypeMessageExt {}
export class Banned extends TypeMessageExt {
showMessage(message: string){

View file

@ -6,11 +6,22 @@ import {GameConnexionTypes, urlManager} from "../Url/UrlManager";
import {localUserStore} from "./LocalUserStore";
import {LocalUser} from "./LocalUser";
import {Room} from "./Room";
import {Subject} from "rxjs";
export enum ConnexionMessageEventTypes {
worldFull = 1,
}
export interface ConnexionMessageEvent {
type: ConnexionMessageEventTypes,
}
class ConnectionManager {
private localUser!:LocalUser;
private connexionType?: GameConnexionTypes
public _connexionMessageStream:Subject<ConnexionMessageEvent> = new Subject();
/**
* Tries to login to the node server and return the starting map url to be loaded
*/

View file

@ -42,14 +42,6 @@ export interface PointInterface {
moving: boolean;
}
export class Point implements PointInterface{
constructor(public x : number, public y : number, public direction : string = PlayerAnimationNames.WalkDown, public moving : boolean = false) {
if(x === null || y === null){
throw Error("position x and y cannot be null");
}
}
}
export interface MessageUserPositionInterface {
userId: number;
name: string;
@ -80,20 +72,10 @@ export interface GroupCreatedUpdatedMessageInterface {
groupSize: number
}
export interface WebRtcStartMessageInterface {
roomId: string,
clients: UserSimplePeerInterface[]
}
export interface WebRtcDisconnectMessageInterface {
userId: number
}
export interface WebRtcSignalSentMessageInterface {
receiverId: number,
signal: SignalData
}
export interface WebRtcSignalReceivedMessageInterface {
userId: number,
signal: SignalData,
@ -113,11 +95,6 @@ export interface ViewportInterface {
bottom: number,
}
export interface BatchedMessageInterface {
event: string,
payload: unknown
}
export interface ItemEventMessageInterface {
itemId: number,
event: string,

View file

@ -43,6 +43,7 @@ import {
} from "./ConnexionModels";
import {BodyResourceDescriptionInterface} from "../Phaser/Entity/PlayerTextures";
import {adminMessagesService} from "./AdminMessagesService";
import {connectionManager, ConnexionMessageEventTypes} from "./ConnectionManager";
const manualPingDelay = 20000;
@ -101,7 +102,7 @@ export class RoomConnection implements RoomConnection {
}
// If we are not connected yet (if a JoinRoomMessage was not sent), we need to retry.
if (this.userId === null) {
if (this.userId === null && !this.closed) {
this.dispatch(EventMessage.CONNECTING_ERROR, event);
}
});
@ -156,7 +157,8 @@ export class RoomConnection implements RoomConnection {
} as RoomJoinedMessageInterface
});
} else if (message.hasErrormessage()) {
console.error(EventMessage.MESSAGE_ERROR, message.getErrormessage()?.getMessage());
connectionManager._connexionMessageStream.next({type: ConnexionMessageEventTypes.worldFull}); //todo: generalize this behavior to all messages
this.closed = true;
} else if (message.hasWebrtcsignaltoclientmessage()) {
this.dispatch(EventMessage.WEBRTC_SIGNAL, message.getWebrtcsignaltoclientmessage());
} else if (message.hasWebrtcscreensharingsignaltoclientmessage()) {

View file

@ -3,25 +3,15 @@ import {
GroupCreatedUpdatedMessageInterface,
MessageUserJoined,
MessageUserMovedInterface,
MessageUserPositionInterface, OnConnectInterface,
MessageUserPositionInterface,
OnConnectInterface,
PointInterface,
PositionInterface,
RoomJoinedMessageInterface
} from "../../Connexion/ConnexionModels";
import {CurrentGamerInterface, hasMovedEventName, Player} from "../Player/Player";
import {
DEBUG_MODE,
JITSI_PRIVATE_MODE,
POSITION_DELAY,
RESOLUTION,
ZOOM_LEVEL
} from "../../Enum/EnvironmentVariable";
import {
ITiledMap,
ITiledMapLayer,
ITiledMapLayerProperty, ITiledMapObject,
ITiledTileSet
} from "../Map/ITiledMap";
import {DEBUG_MODE, JITSI_PRIVATE_MODE, POSITION_DELAY, RESOLUTION, ZOOM_LEVEL} from "../../Enum/EnvironmentVariable";
import {ITiledMap, ITiledMapLayer, ITiledMapLayerProperty, ITiledMapObject, ITiledTileSet} from "../Map/ITiledMap";
import {AddPlayerInterface} from "./AddPlayerInterface";
import {PlayerAnimationNames} from "../Player/Animation";
import {PlayerMovement} from "./PlayerMovement";
@ -41,11 +31,6 @@ import {
TRIGGER_WEBSITE_PROPERTIES,
WEBSITE_MESSAGE_PROPERTIES
} from "../../WebRtc/LayoutManager";
import Texture = Phaser.Textures.Texture;
import Sprite = Phaser.GameObjects.Sprite;
import CanvasTexture = Phaser.Textures.CanvasTexture;
import GameObject = Phaser.GameObjects.GameObject;
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
import {GameMap} from "./GameMap";
import {coWebsiteManager} from "../../WebRtc/CoWebsiteManager";
import {mediaManager} from "../../WebRtc/MediaManager";
@ -54,7 +39,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} from "../../Connexion/ConnectionManager";
import {connectionManager, ConnexionMessageEvent, ConnexionMessageEventTypes} from "../../Connexion/ConnectionManager";
import {RoomConnection} from "../../Connexion/RoomConnection";
import {GlobalMessageManager} from "../../Administration/GlobalMessageManager";
import {userMessageManager} from "../../Administration/UserMessageManager";
@ -72,6 +57,12 @@ import {TextureError} from "../../Exception/TextureError";
import {addLoader} from "../Components/Loader";
import {ErrorSceneName} from "../Reconnecting/ErrorScene";
import {localUserStore} from "../../Connexion/LocalUserStore";
import Texture = Phaser.Textures.Texture;
import Sprite = Phaser.GameObjects.Sprite;
import CanvasTexture = Phaser.Textures.CanvasTexture;
import GameObject = Phaser.GameObjects.GameObject;
import FILE_LOAD_ERROR = Phaser.Loader.Events.FILE_LOAD_ERROR;
import {Subscription} from "rxjs";
export interface GameSceneInitInterface {
initPosition: PointInterface|null,
@ -157,11 +148,12 @@ export class GameScene extends ResizableScene implements CenterListener {
// The item that can be selected by pressing the space key.
private outlinedItem: ActionableItem|null = null;
public userInputManager!: UserInputManager;
private isReconnecting: boolean = false;
private isReconnecting: boolean|undefined = undefined;
private startLayerName!: string | null;
private openChatIcon!: OpenChatIcon;
private playerName!: string;
private characterLayers!: string[];
private messageSubscription: Subscription|null = null;
constructor(private room: Room, MapUrlFile: string, customKey?: string|undefined) {
super({
@ -293,25 +285,6 @@ export class GameScene extends ResizableScene implements CenterListener {
}
});
});
// import(/* webpackIgnore: true */ scriptUrl).then(result => {
//
// result.default.preload(this.load);
//
// this.load.start(); // Let's manually start the loader because the import might be over AFTER the loading ends.
// this.load.on('complete', () => {
// // FIXME: the factory might fail because the resources might not be loaded yet...
// // We would need to add a loader ended event in addition to the createPromise
// this.createPromise.then(() => {
// result.default.create(this);
//
// for (let object of objectsOfType) {
// // TODO: we should pass here a factory to create sprites (maybe?)
// let objectSprite = result.default.factory(this, object);
// }
// });
// });
// });
}
}
@ -330,6 +303,8 @@ export class GameScene extends ResizableScene implements CenterListener {
gameManager.gameSceneIsCreated(this);
urlManager.pushRoomIdToUrl(this.room);
this.startLayerName = urlManager.getStartLayerNameFromUrl();
this.messageSubscription = connectionManager._connexionMessageStream.subscribe((event) => this.onConnexionMessage(event))
const playerName = gameManager.getPlayerName();
if (!playerName) {
@ -401,13 +376,13 @@ export class GameScene extends ResizableScene implements CenterListener {
this.scene.launch(ReconnectingSceneName);
}, 0);
} else if (this.connection === undefined) {
// Let's wait 0.5 seconds before printing the "connecting" screen to avoid blinking
// Let's wait 1 second before printing the "connecting" screen to avoid blinking
setTimeout(() => {
if (this.connection === undefined) {
this.scene.sleep();
this.scene.launch(ReconnectingSceneName);
}
}, 500);
}, 1000);
}
this.createPromiseResolve();
@ -569,8 +544,6 @@ export class GameScene extends ResizableScene implements CenterListener {
//init user position and play trigger to check layers properties
this.gameMap.setPosition(this.CurrentPlayer.x, this.CurrentPlayer.y);
return this.connection;
});
}
@ -607,30 +580,7 @@ export class GameScene extends ResizableScene implements CenterListener {
contextRed.stroke();
this.circleRedTexture.refresh();
}
private playAudio(url: string|number|boolean|undefined, loop=false): void {
if (url === undefined) {
audioManager.unloadAudio();
} else {
const audioPath = url as string;
let realAudioPath = '';
if (audioPath.indexOf('://') > 0) {
// remote file or stream
realAudioPath = audioPath;
} else {
// local file, include it relative to map directory
const mapDirUrl = this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf('/'));
realAudioPath = mapDirUrl + '/' + url;
}
audioManager.loadAudio(realAudioPath);
if (loop) {
audioManager.loop();
}
}
}
private safeParseJSONstring(jsonString: string|undefined, propertyName: string) {
try {
@ -711,15 +661,19 @@ export class GameScene extends ResizableScene implements CenterListener {
}
});
this.gameMap.onPropertyChange('playAudio', (newValue, oldValue) => {
this.playAudio(newValue);
newValue === undefined ? audioManager.unloadAudio() : audioManager.playAudio(newValue, this.getMapDirUrl());
});
this.gameMap.onPropertyChange('playAudioLoop', (newValue, oldValue) => {
this.playAudio(newValue, true);
newValue === undefined ? audioManager.unloadAudio() : audioManager.playAudio(newValue, this.getMapDirUrl());
});
}
private getMapDirUrl(): string {
return this.MapUrlFile.substr(0, this.MapUrlFile.lastIndexOf('/'));
}
private onMapExit(exitKey: string) {
const {roomId, hash} = Room.getIdFromIdentifier(exitKey, this.MapUrlFile, this.instance);
if (!roomId) throw new Error('Could not find the room from its exit key: '+exitKey);
@ -745,14 +699,11 @@ export class GameScene extends ResizableScene implements CenterListener {
// stop playing audio, close any open website, stop any open Jitsi
coWebsiteManager.closeCoWebsite();
this.stopJitsi();
this.playAudio(undefined);
audioManager.unloadAudio();
// We are completely destroying the current scene to avoid using a half-backed instance when coming back to the same map.
if(this.connection) {
this.connection.closeConnection();
}
if(this.simplePeer) {
this.simplePeer.unregister();
}
this.connection?.closeConnection();
this.simplePeer?.unregister();
this.messageSubscription?.unsubscribe();
}
private removeAllRemotePlayers(): void {
@ -1267,21 +1218,34 @@ export class GameScene extends ResizableScene implements CenterListener {
}
public stopJitsi(): void {
this.connection.setSilent(false);
this.connection?.setSilent(false);
jitsiFactory.stop();
mediaManager.showGameOverlay();
mediaManager.removeTriggerCloseJitsiFrameButton('close-jisi');
}
//todo: into onConnexionMessage
private bannedUser(){
this.cleanupClosingScene();
this.userInputManager.clearAllKeys();
this.scene.start(ErrorSceneName, {
title: 'Banned',
subTitle: 'You was banned of WorkAdventure',
message: 'If you want more information, you can contact us: workadventure@thecodingmachine.com'
subTitle: 'You were banned from WorkAdventure',
message: 'If you want more information, you may contact us at: workadventure@thecodingmachine.com'
});
}
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'
});
}
}
}

View file

@ -38,6 +38,25 @@ class AudioManager {
HtmlUtils.getElementByIdOrFail<HTMLInputElement>('audioplayer_volume').value = '' + this.volume;
}
public playAudio(url: string|number|boolean, mapDirUrl: string, loop=false): void {
const audioPath = url as string;
let realAudioPath = '';
if (audioPath.indexOf('://') > 0) {
// remote file or stream
realAudioPath = audioPath;
} else {
// local file, include it relative to map directory
realAudioPath = mapDirUrl + '/' + url;
}
this.loadAudio(realAudioPath);
if (loop) {
this.loop();
}
}
private close(): void {
this.audioPlayerCtrl.classList.remove('loading');
this.audioPlayerCtrl.classList.add('hidden');
@ -75,7 +94,7 @@ class AudioManager {
}
public loadAudio(url: string): void {
private loadAudio(url: string): void {
this.load();
/* Solution 1, remove whole audio player */
@ -125,7 +144,7 @@ class AudioManager {
this.open();
}
public loop(): void {
private loop(): void {
if (this.audioPlayerElem !== undefined) {
this.audioPlayerElem.loop = true;
}