431 lines
12 KiB
TypeScript
431 lines
12 KiB
TypeScript
import { Application, IApplicationOptions } from '@pixi/app';
|
|
import { SCALE_MODES } from '@pixi/constants';
|
|
import { settings } from '@pixi/settings';
|
|
import { Ticker } from '@pixi/ticker';
|
|
import { INitroManager } from '../core';
|
|
import { ConfigurationEvent } from '../core/configuration/ConfigurationEvent';
|
|
import { EventDispatcher } from '../core/events/EventDispatcher';
|
|
import { IEventDispatcher } from '../core/events/IEventDispatcher';
|
|
import { ILinkEventTracker } from '../core/events/ILinkEventTracker';
|
|
import { IWorkerEventTracker } from '../core/events/IWorkerEventTracker';
|
|
import { NitroEvent } from '../core/events/NitroEvent';
|
|
import { INitroCore } from '../core/INitroCore';
|
|
import { NitroCore } from '../core/NitroCore';
|
|
import { NitroTimer } from '../core/utils/NitroTimer';
|
|
import { IRoomManager } from '../room/IRoomManager';
|
|
import { RoomManager } from '../room/RoomManager';
|
|
import { AvatarRenderManager } from './avatar/AvatarRenderManager';
|
|
import { IAvatarRenderManager } from './avatar/IAvatarRenderManager';
|
|
import { IRoomCameraWidgetManager } from './camera/IRoomCameraWidgetManager';
|
|
import { RoomCameraWidgetManager } from './camera/RoomCameraWidgetManager';
|
|
import { INitroCommunicationManager } from './communication/INitroCommunicationManager';
|
|
import { NitroCommunicationManager } from './communication/NitroCommunicationManager';
|
|
import { LegacyExternalInterface } from './externalInterface/LegacyExternalInterface';
|
|
import { GameMessageHandler } from './game/GameMessageHandler';
|
|
import { INitro } from './INitro';
|
|
import { INitroLocalizationManager } from './localization/INitroLocalizationManager';
|
|
import { NitroLocalizationManager } from './localization/NitroLocalizationManager';
|
|
import './Plugins';
|
|
import { RoomEngineEvent } from './room/events/RoomEngineEvent';
|
|
import { IRoomEngine } from './room/IRoomEngine';
|
|
import { RoomEngine } from './room/RoomEngine';
|
|
import { IRoomSessionManager } from './session/IRoomSessionManager';
|
|
import { ISessionDataManager } from './session/ISessionDataManager';
|
|
import { RoomSessionManager } from './session/RoomSessionManager';
|
|
import { SessionDataManager } from './session/SessionDataManager';
|
|
import { SoundManager } from './sound/SoundManager';
|
|
import { HabboWebTools } from './utils/HabboWebTools';
|
|
|
|
LegacyExternalInterface.available;
|
|
|
|
settings.SCALE_MODE = SCALE_MODES.NEAREST;
|
|
settings.ROUND_PIXELS = true;
|
|
|
|
export class Nitro extends Application implements INitro
|
|
{
|
|
public static WEBGL_CONTEXT_LOST: string = 'NE_WEBGL_CONTEXT_LOST';
|
|
public static WEBGL_UNAVAILABLE: string = 'NE_WEBGL_UNAVAILABLE';
|
|
public static READY: string = 'NE_READY!';
|
|
|
|
private static INSTANCE: INitro = null;
|
|
|
|
private _nitroTimer: NitroTimer;
|
|
private _worker: Worker;
|
|
private _core: INitroCore;
|
|
private _events: IEventDispatcher;
|
|
private _localization: INitroLocalizationManager;
|
|
private _communication: INitroCommunicationManager;
|
|
private _avatar: IAvatarRenderManager;
|
|
private _roomEngine: IRoomEngine;
|
|
private _sessionDataManager: ISessionDataManager;
|
|
private _roomSessionManager: IRoomSessionManager;
|
|
private _roomManager: IRoomManager;
|
|
private _cameraManager: IRoomCameraWidgetManager;
|
|
private _soundManager: INitroManager;
|
|
private _linkTrackers: ILinkEventTracker[];
|
|
private _workerTrackers: IWorkerEventTracker[];
|
|
|
|
private _isReady: boolean;
|
|
private _isDisposed: boolean;
|
|
|
|
constructor(core: INitroCore, options?: IApplicationOptions)
|
|
{
|
|
super(options);
|
|
|
|
if(!Nitro.INSTANCE) Nitro.INSTANCE = this;
|
|
|
|
this._nitroTimer = new NitroTimer();
|
|
this._worker = null;
|
|
this._core = core;
|
|
this._events = new EventDispatcher();
|
|
this._localization = new NitroLocalizationManager();
|
|
this._communication = new NitroCommunicationManager(core.communication);
|
|
this._avatar = new AvatarRenderManager();
|
|
this._roomEngine = new RoomEngine(this._communication);
|
|
this._sessionDataManager = new SessionDataManager(this._communication);
|
|
this._roomSessionManager = new RoomSessionManager(this._communication, this._roomEngine);
|
|
this._roomManager = new RoomManager(this._roomEngine, this._roomEngine.visualizationFactory, this._roomEngine.logicFactory);
|
|
this._cameraManager = new RoomCameraWidgetManager();
|
|
this._soundManager = new SoundManager();
|
|
this._linkTrackers = [];
|
|
this._workerTrackers = [];
|
|
|
|
this._isReady = false;
|
|
this._isDisposed = false;
|
|
|
|
this._core.configuration.events.addEventListener(ConfigurationEvent.LOADED, this.onConfigurationLoadedEvent.bind(this));
|
|
this._roomEngine.events.addEventListener(RoomEngineEvent.ENGINE_INITIALIZED, this.onRoomEngineReady.bind(this));
|
|
|
|
if(this._worker) this._worker.onmessage = this.createWorkerEvent.bind(this);
|
|
}
|
|
|
|
public static bootstrap(): void
|
|
{
|
|
if(Nitro.INSTANCE)
|
|
{
|
|
Nitro.INSTANCE.dispose();
|
|
|
|
Nitro.INSTANCE = null;
|
|
}
|
|
|
|
const canvas = document.createElement('canvas');
|
|
|
|
canvas.id = 'client-wrapper';
|
|
canvas.className = 'client-canvas';
|
|
|
|
const instance = new this(new NitroCore(), {
|
|
autoDensity: true,
|
|
resolution: window.devicePixelRatio,
|
|
width: window.innerWidth,
|
|
height: window.innerHeight,
|
|
view: canvas
|
|
});
|
|
|
|
canvas.addEventListener('webglcontextlost', () => instance.events.dispatchEvent(new NitroEvent(Nitro.WEBGL_CONTEXT_LOST)));
|
|
}
|
|
|
|
public init(): void
|
|
{
|
|
if(this._isReady || this._isDisposed) return;
|
|
|
|
if(this._avatar) this._avatar.init();
|
|
|
|
if(this._soundManager) this._soundManager.init();
|
|
|
|
if(this._roomEngine)
|
|
{
|
|
this._roomEngine.sessionDataManager = this._sessionDataManager;
|
|
this._roomEngine.roomSessionManager = this._roomSessionManager;
|
|
this._roomEngine.roomManager = this._roomManager;
|
|
|
|
if(this._sessionDataManager) this._sessionDataManager.init();
|
|
if(this._roomSessionManager) this._roomSessionManager.init();
|
|
|
|
this._roomEngine.init();
|
|
}
|
|
|
|
if(!this._communication.connection)
|
|
{
|
|
throw new Error('No connection found');
|
|
}
|
|
|
|
new GameMessageHandler(this._communication.connection);
|
|
|
|
this._isReady = true;
|
|
}
|
|
|
|
public dispose(): void
|
|
{
|
|
if(this._isDisposed) return;
|
|
|
|
if(this._roomManager)
|
|
{
|
|
this._roomManager.dispose();
|
|
|
|
this._roomManager = null;
|
|
}
|
|
|
|
if(this._roomSessionManager)
|
|
{
|
|
this._roomSessionManager.dispose();
|
|
|
|
this._roomSessionManager = null;
|
|
}
|
|
|
|
if(this._sessionDataManager)
|
|
{
|
|
this._sessionDataManager.dispose();
|
|
|
|
this._sessionDataManager = null;
|
|
}
|
|
|
|
if(this._roomEngine)
|
|
{
|
|
this._roomEngine.dispose();
|
|
|
|
this._roomEngine = null;
|
|
}
|
|
|
|
if(this._avatar)
|
|
{
|
|
this._avatar.dispose();
|
|
|
|
this._avatar = null;
|
|
}
|
|
|
|
if(this._soundManager)
|
|
{
|
|
this._soundManager.dispose();
|
|
|
|
this._soundManager = null;
|
|
}
|
|
|
|
if(this._communication)
|
|
{
|
|
this._communication.dispose();
|
|
|
|
this._communication = null;
|
|
}
|
|
|
|
super.destroy();
|
|
|
|
this._isDisposed = true;
|
|
this._isReady = false;
|
|
}
|
|
|
|
private onConfigurationLoadedEvent(event: ConfigurationEvent): void
|
|
{
|
|
const animationFPS = this.getConfiguration<number>('system.animation.fps', 24);
|
|
const limitsFPS = this.getConfiguration<boolean>('system.limits.fps', true);
|
|
|
|
if(limitsFPS) Nitro.instance.ticker.maxFPS = animationFPS;
|
|
}
|
|
|
|
private onRoomEngineReady(event: RoomEngineEvent): void
|
|
{
|
|
this.startSendingHeartBeat();
|
|
}
|
|
|
|
public getConfiguration<T>(key: string, value: T = null): T
|
|
{
|
|
return this._core.configuration.getValue<T>(key, value);
|
|
}
|
|
|
|
public getLocalization(key: string): string
|
|
{
|
|
return this._localization.getValue(key);
|
|
}
|
|
|
|
public getLocalizationWithParameter(key: string, parameter: string, replacement: string): string
|
|
{
|
|
return this._localization.getValueWithParameter(key, parameter, replacement);
|
|
}
|
|
|
|
public getLocalizationWithParameters(key: string, parameters: string[], replacements: string[]): string
|
|
{
|
|
return this._localization.getValueWithParameters(key, parameters, replacements);
|
|
}
|
|
|
|
public addWorkerEventTracker(tracker: IWorkerEventTracker): void
|
|
{
|
|
if(this._workerTrackers.indexOf(tracker) >= 0) return;
|
|
|
|
this._workerTrackers.push(tracker);
|
|
}
|
|
|
|
public removeWorkerEventTracker(tracker: IWorkerEventTracker): void
|
|
{
|
|
const index = this._workerTrackers.indexOf(tracker);
|
|
|
|
if(index === -1) return;
|
|
|
|
this._workerTrackers.splice(index, 1);
|
|
}
|
|
|
|
public createWorkerEvent(message: MessageEvent): void
|
|
{
|
|
if(!message) return;
|
|
|
|
const data: { [index: string]: any } = message.data;
|
|
|
|
for(const tracker of this._workerTrackers)
|
|
{
|
|
if(!tracker) continue;
|
|
|
|
tracker.workerMessageReceived(data);
|
|
}
|
|
}
|
|
|
|
public sendWorkerEvent(message: { [index: string]: any }): void
|
|
{
|
|
if(!message || !this._worker) return;
|
|
|
|
this._worker.postMessage(message);
|
|
}
|
|
|
|
public addLinkEventTracker(tracker: ILinkEventTracker): void
|
|
{
|
|
if(this._linkTrackers.indexOf(tracker) >= 0) return;
|
|
|
|
this._linkTrackers.push(tracker);
|
|
}
|
|
|
|
public removeLinkEventTracker(tracker: ILinkEventTracker): void
|
|
{
|
|
const index = this._linkTrackers.indexOf(tracker);
|
|
|
|
if(index === -1) return;
|
|
|
|
this._linkTrackers.splice(index, 1);
|
|
}
|
|
|
|
public createLinkEvent(link: string): void
|
|
{
|
|
if(!link || (link === '')) return;
|
|
|
|
for(const tracker of this._linkTrackers)
|
|
{
|
|
if(!tracker) continue;
|
|
|
|
const prefix = tracker.eventUrlPrefix;
|
|
|
|
if(prefix.length > 0)
|
|
{
|
|
if(link.substr(0, prefix.length) === prefix) tracker.linkReceived(link);
|
|
}
|
|
else
|
|
{
|
|
tracker.linkReceived(link);
|
|
}
|
|
}
|
|
}
|
|
|
|
private startSendingHeartBeat(): void
|
|
{
|
|
this.sendHeartBeat();
|
|
|
|
setInterval(this.sendHeartBeat, 10000);
|
|
}
|
|
|
|
private sendHeartBeat(): void
|
|
{
|
|
HabboWebTools.sendHeartBeat();
|
|
}
|
|
|
|
public setWorker(val: Worker): void
|
|
{
|
|
this._worker = val;
|
|
this._worker.onmessage = this.createWorkerEvent.bind(this);
|
|
}
|
|
|
|
public get nitroTimer(): NitroTimer
|
|
{
|
|
return this._nitroTimer;
|
|
}
|
|
|
|
public get core(): INitroCore
|
|
{
|
|
return this._core;
|
|
}
|
|
|
|
public get events(): IEventDispatcher
|
|
{
|
|
return this._events;
|
|
}
|
|
|
|
public get localization(): INitroLocalizationManager
|
|
{
|
|
return this._localization;
|
|
}
|
|
|
|
public get communication(): INitroCommunicationManager
|
|
{
|
|
return this._communication;
|
|
}
|
|
|
|
public get avatar(): IAvatarRenderManager
|
|
{
|
|
return this._avatar;
|
|
}
|
|
|
|
public get roomEngine(): IRoomEngine
|
|
{
|
|
return this._roomEngine;
|
|
}
|
|
|
|
public get sessionDataManager(): ISessionDataManager
|
|
{
|
|
return this._sessionDataManager;
|
|
}
|
|
|
|
public get roomSessionManager(): IRoomSessionManager
|
|
{
|
|
return this._roomSessionManager;
|
|
}
|
|
|
|
public get roomManager(): IRoomManager
|
|
{
|
|
return this._roomManager;
|
|
}
|
|
|
|
public get cameraManager(): IRoomCameraWidgetManager
|
|
{
|
|
return this._cameraManager;
|
|
}
|
|
|
|
public get width(): number
|
|
{
|
|
return (this.renderer.width / this.renderer.resolution);
|
|
}
|
|
|
|
public get height(): number
|
|
{
|
|
return (this.renderer.height / this.renderer.resolution);
|
|
}
|
|
|
|
public get ticker(): Ticker
|
|
{
|
|
return Ticker.shared;
|
|
}
|
|
|
|
public get time(): number
|
|
{
|
|
return this.ticker.lastTime;
|
|
}
|
|
|
|
public get isReady(): boolean
|
|
{
|
|
return this._isReady;
|
|
}
|
|
|
|
public get isDisposed(): boolean
|
|
{
|
|
return this._isDisposed;
|
|
}
|
|
|
|
public static get instance(): INitro
|
|
{
|
|
return this.INSTANCE || null;
|
|
}
|
|
}
|