nitro/libs/renderer/src/nitro/room/RoomEngine.ts

3574 lines
114 KiB
TypeScript

import {RenderTexture, Resource, Texture} from "@pixi/core";
import {Container, DisplayObject} from "@pixi/display";
import {Matrix, Point, Rectangle} from "@pixi/math";
import {
IConnection,
IDisposable,
IFurnitureStackingHeightMap,
IGetImageListener,
IImageResult,
ILegacyWallGeometry,
IMessageComposer,
INitroCommunicationManager,
INitroEvent,
IObjectData,
IPetColorResult,
IPetCustomPart,
IRoomContentListener,
IRoomContentLoader,
IRoomCreator,
IRoomEngine,
IRoomEngineServices,
IRoomGeometry,
IRoomInstance,
IRoomManager,
IRoomManagerListener,
IRoomObject,
IRoomObjectController,
IRoomObjectLogicFactory,
IRoomObjectVisualizationFactory,
IRoomRenderer,
IRoomRendererFactory,
IRoomRenderingCanvas,
IRoomSessionManager,
ISelectedRoomObjectData,
ISessionDataManager,
ITileObjectMap,
IUpdateReceiver,
IVector3D,
LegacyDataType,
MouseEventType,
NitroConfiguration,
NitroLogger,
ObjectDataFactory,
RoomControllerLevel,
RoomObjectCategory,
RoomObjectUserType,
RoomObjectVariable,
ToolbarIconEnum,
Vector3d,
} from "../../api";
import {NitroManager} from "../../core";
import {
BadgeImageReadyEvent,
NitroToolbarAnimateIconEvent,
RoomBackgroundColorEvent,
RoomDragEvent,
RoomEngineEvent,
RoomEngineObjectEvent,
RoomObjectEvent,
RoomObjectFurnitureActionEvent,
RoomObjectMouseEvent,
RoomSessionEvent,
RoomToObjectOwnAvatarMoveEvent,
} from "../../events";
import {GetTicker, GetTickerTime, NitroSprite, TextureUtils} from "../../pixi-proxy";
import {NumberBank, RoomEnterEffect, RoomGeometry, RoomInstance, RoomObjectUpdateMessage, RoomRendererFactory} from "../../room";
import {PetFigureData} from "../avatar";
import {RenderRoomMessageComposer, RenderRoomThumbnailMessageComposer} from "../communication";
import {FurniId} from "../utils";
import {ImageResult} from "./ImageResult";
import {RoomContentLoader} from "./RoomContentLoader";
import {RoomMessageHandler} from "./RoomMessageHandler";
import {RoomObjectEventHandler} from "./RoomObjectEventHandler";
import {RoomObjectLogicFactory} from "./RoomObjectLogicFactory";
import {RoomVariableEnum} from "./RoomVariableEnum";
import {
ObjectAvatarCarryObjectUpdateMessage,
ObjectAvatarChatUpdateMessage,
ObjectAvatarDanceUpdateMessage,
ObjectAvatarEffectUpdateMessage,
ObjectAvatarExperienceUpdateMessage,
ObjectAvatarExpressionUpdateMessage,
ObjectAvatarFigureUpdateMessage,
ObjectAvatarFlatControlUpdateMessage,
ObjectAvatarGestureUpdateMessage,
ObjectAvatarGuideStatusUpdateMessage,
ObjectAvatarMutedUpdateMessage,
ObjectAvatarOwnMessage,
ObjectAvatarPetGestureUpdateMessage,
ObjectAvatarPlayerValueUpdateMessage,
ObjectAvatarPlayingGameUpdateMessage,
ObjectAvatarPostureUpdateMessage,
ObjectAvatarSignUpdateMessage,
ObjectAvatarSleepUpdateMessage,
ObjectAvatarTypingUpdateMessage,
ObjectAvatarUpdateMessage,
ObjectAvatarUseObjectUpdateMessage,
ObjectDataUpdateMessage,
ObjectGroupBadgeUpdateMessage,
ObjectHeightUpdateMessage,
ObjectItemDataUpdateMessage,
ObjectModelDataUpdateMessage,
ObjectMoveUpdateMessage,
ObjectRoomColorUpdateMessage,
ObjectRoomFloorHoleUpdateMessage,
ObjectRoomMaskUpdateMessage,
ObjectRoomPlanePropertyUpdateMessage,
ObjectRoomPlaneVisibilityUpdateMessage,
ObjectRoomUpdateMessage,
ObjectStateUpdateMessage,
} from "./messages";
import {RoomLogic, RoomMapData, RoomObjectVisualizationFactory} from "./object";
import {RoomCamera, RoomData, RoomFurnitureData, RoomInstanceData, RoomObjectBadgeImageAssetListener, SpriteDataCollector} from "./utils";
export class RoomEngine
extends NitroManager
implements IRoomEngine, IRoomCreator, IRoomEngineServices, IRoomManagerListener, IRoomContentListener, IUpdateReceiver, IDisposable
{
public static ROOM_OBJECT_ID: number = -1;
public static ROOM_OBJECT_TYPE: string = "room";
public static CURSOR_OBJECT_ID: number = -2;
public static CURSOR_OBJECT_TYPE: string = "tile_cursor";
public static ARROW_OBJECT_ID: number = -3;
public static ARROW_OBJECT_TYPE: string = "selection_arrow";
public static OVERLAY: string = "overlay";
public static OBJECT_ICON_SPRITE: string = "object_icon_sprite";
private static DRAG_THRESHOLD: number = 15;
private static TEMPORARY_ROOM: string = "temporary_room";
private _communication: INitroCommunicationManager;
private _roomRendererFactory: IRoomRendererFactory;
private _roomManager: IRoomManager;
private _visualizationFactory: IRoomObjectVisualizationFactory;
private _sessionDataManager: ISessionDataManager;
private _roomSessionManager: IRoomSessionManager;
private _roomObjectEventHandler: RoomObjectEventHandler;
private _roomMessageHandler: RoomMessageHandler;
private _roomContentLoader: IRoomContentLoader;
private _ready: boolean;
private _roomContentLoaderReady: boolean;
private _imageObjectIdBank: NumberBank;
private _imageCallbacks: Map<string, IGetImageListener[]>;
private _thumbnailObjectIdBank: NumberBank;
private _thumbnailCallbacks: Map<string, IGetImageListener[]>;
private _activeRoomId: number;
private _activeRoomActiveCanvas: number;
private _activeRoomActiveCanvasMouseX: number;
private _activeRoomActiveCanvasMouseY: number;
private _activeRoomIsDragged: boolean;
private _activeRoomWasDragged: boolean;
private _activeRoomDragStartX: number;
private _activeRoomDragStartY: number;
private _activeRoomDragX: number;
private _activeRoomDragY: number;
private _roomDraggingAlwaysCenters: boolean;
private _roomAllowsDragging: boolean;
private _roomDatas: Map<number, RoomData>;
private _roomInstanceDatas: Map<number, RoomInstanceData>;
private _skipFurnitureCreationForNextFrame: boolean;
private _mouseCursorUpdate: boolean;
private _badgeListenerObjects: Map<string, RoomObjectBadgeImageAssetListener[]>;
private _logicFactory: IRoomObjectLogicFactory;
constructor(communication: INitroCommunicationManager) {
super();
this._communication = communication;
this._sessionDataManager = null;
this._roomSessionManager = null;
this._roomManager = null;
this._roomObjectEventHandler = new RoomObjectEventHandler(this);
this._roomMessageHandler = new RoomMessageHandler(this);
this._roomContentLoader = new RoomContentLoader();
this._ready = false;
this._roomContentLoaderReady = false;
this._activeRoomId = -1;
this._activeRoomActiveCanvas = -1;
this._roomInstanceDatas = new Map();
this._roomDatas = new Map();
this._roomRendererFactory = new RoomRendererFactory();
this._visualizationFactory = new RoomObjectVisualizationFactory();
this._logicFactory = new RoomObjectLogicFactory();
this._activeRoomActiveCanvasMouseX = 0;
this._activeRoomActiveCanvasMouseY = 0;
this._activeRoomIsDragged = false;
this._activeRoomWasDragged = false;
this._activeRoomDragStartX = 0;
this._activeRoomDragStartY = 0;
this._activeRoomDragX = 0;
this._activeRoomDragY = 0;
this._skipFurnitureCreationForNextFrame = false;
this._mouseCursorUpdate = false;
this._imageObjectIdBank = null;
this._imageCallbacks = new Map();
this._thumbnailCallbacks = new Map();
this._roomDraggingAlwaysCenters = false;
this._roomAllowsDragging = true;
this._badgeListenerObjects = new Map();
this.runVisibilityUpdate = this.runVisibilityUpdate.bind(this);
this.processRoomObjectEvent = this.processRoomObjectEvent.bind(this);
this.onRoomSessionEvent = this.onRoomSessionEvent.bind(this);
this.onRoomContentLoaderReadyEvent = this.onRoomContentLoaderReadyEvent.bind(this);
this.onBadgeImageReadyEvent = this.onBadgeImageReadyEvent.bind(this);
}
public override onInit(): void {
if (this._ready) return;
this._imageObjectIdBank = new NumberBank(1000);
this._thumbnailObjectIdBank = new NumberBank(1000);
this._logicFactory.registerEventFunction(this.processRoomObjectEvent);
if (this._roomManager) {
this._roomManager.setContentLoader(this._roomContentLoader);
this._roomManager.addUpdateCategory(RoomObjectCategory.FLOOR);
this._roomManager.addUpdateCategory(RoomObjectCategory.WALL);
this._roomManager.addUpdateCategory(RoomObjectCategory.UNIT);
this._roomManager.addUpdateCategory(RoomObjectCategory.CURSOR);
this._roomManager.addUpdateCategory(RoomObjectCategory.ROOM);
}
this._roomMessageHandler.setConnection(this._communication.connection);
this._roomContentLoader.initialize(this.events);
this._roomContentLoader.setSessionDataManager(this._sessionDataManager);
this._roomContentLoader.setIconListener(this);
if (this._roomSessionManager) {
this._roomSessionManager.events.addEventListener(RoomSessionEvent.STARTED, this.onRoomSessionEvent);
this._roomSessionManager.events.addEventListener(RoomSessionEvent.ENDED, this.onRoomSessionEvent);
}
this.events.addEventListener(RoomContentLoader.LOADER_READY, this.onRoomContentLoaderReadyEvent);
GetTicker().add(this.update, this);
document.addEventListener("visibilitychange", this.runVisibilityUpdate);
}
public override onDispose(): void {
if (!this._ready) return;
for (const [key, value] of this._roomInstanceDatas) {
this.removeRoomInstance(key);
}
document.removeEventListener("visibilitychange", this.runVisibilityUpdate);
GetTicker().remove(this.update, this);
if (this._roomObjectEventHandler) this._roomObjectEventHandler.dispose();
if (this._roomMessageHandler) this._roomMessageHandler.dispose();
if (this._roomContentLoader) this._roomContentLoader.dispose();
this.events.removeEventListener(RoomContentLoader.LOADER_READY, this.onRoomContentLoaderReadyEvent);
if (this._roomSessionManager) {
this._roomSessionManager.events.removeEventListener(RoomSessionEvent.STARTED, this.onRoomSessionEvent);
this._roomSessionManager.events.removeEventListener(RoomSessionEvent.ENDED, this.onRoomSessionEvent);
}
super.onDispose();
}
private onRoomSessionEvent(event: RoomSessionEvent): void {
if (!(event instanceof RoomSessionEvent)) return;
switch (event.type) {
case RoomSessionEvent.STARTED:
if (this._roomMessageHandler) this._roomMessageHandler.setRoomId(event.session.roomId);
return;
case RoomSessionEvent.ENDED:
if (this._roomMessageHandler) {
this._roomMessageHandler.clearRoomId();
this.removeRoomInstance(event.session.roomId);
}
return;
}
}
private onRoomContentLoaderReadyEvent(event: INitroEvent): void {
this._roomContentLoaderReady = true;
this._roomManager.init();
}
public setActiveRoomId(roomId: number): void {
this._activeRoomId = roomId;
}
public destroyRoom(roomId: number): void {
this.removeRoomInstance(roomId);
}
public getRoomInstance(roomId: number): IRoomInstance {
return (this._roomManager && this._roomManager.getRoomInstance(this.getRoomId(roomId))) || null;
}
public removeRoomInstance(roomId: number): void {
const instance = this.getRoomInstance(roomId);
if (instance) {
this._roomManager && this._roomManager.removeRoomInstance(this.getRoomId(roomId));
}
const existing = this._roomInstanceDatas.get(roomId);
if (existing) {
this._roomInstanceDatas.delete(existing.roomId);
existing.dispose();
}
this.events.dispatchEvent(new RoomEngineEvent(RoomEngineEvent.DISPOSED, roomId));
}
public createRoomInstance(roomId: number, roomMap: RoomMapData): void {
let floorType = "111";
let wallType = "201";
let landscapeType = "1";
if (!this._ready) {
let data = this._roomDatas.get(roomId);
if (data) {
this._roomDatas.delete(roomId);
floorType = data.floorType;
wallType = data.wallType;
landscapeType = data.landscapeType;
}
data = new RoomData(roomId, roomMap);
data.floorType = floorType;
data.wallType = wallType;
data.landscapeType = landscapeType;
this._roomDatas.set(roomId, data);
NitroLogger.warn("Room Engine not initilized yet, can not create room. Room data stored for later initialization.");
return;
}
if (!roomMap) {
NitroLogger.warn("Room property messages");
return;
}
const data = this._roomDatas.get(roomId);
if (data) {
this._roomDatas.delete(roomId);
if (data.floorType) floorType = data.floorType;
if (data.wallType) wallType = data.wallType;
if (data.landscapeType) landscapeType = data.landscapeType;
}
const instance = this.setupRoomInstance(roomId, roomMap, floorType, wallType, landscapeType, this.getRoomInstanceModelName(roomId));
if (!instance) return;
if (roomMap.restrictsDragging) {
this._roomAllowsDragging = false;
} else {
this._roomAllowsDragging = true;
}
this.events.dispatchEvent(new RoomEngineEvent(RoomEngineEvent.INITIALIZED, roomId));
}
private setupRoomInstance(
roomId: number,
roomMap: RoomMapData,
floorType: string,
wallType: string,
landscapeType: string,
worldType: string
): IRoomInstance {
if (!this._ready || !this._roomManager) return null;
const instance = this._roomManager.createRoomInstance(this.getRoomId(roomId));
if (!instance) return null;
const category = RoomObjectCategory.ROOM;
const roomObject = instance.createRoomObjectAndInitalize(RoomEngine.ROOM_OBJECT_ID, RoomEngine.ROOM_OBJECT_TYPE, category) as IRoomObjectController;
instance.model.setValue(RoomVariableEnum.ROOM_IS_PUBLIC, 0);
instance.model.setValue(RoomVariableEnum.ROOM_Z_SCALE, 1);
if (roomMap) {
instance.model.setValue(RoomVariableEnum.RESTRICTS_DRAGGING, roomMap.restrictsDragging);
instance.model.setValue(RoomVariableEnum.RESTRICTS_SCALING, roomMap.restrictsScaling);
instance.model.setValue(RoomVariableEnum.RESTRICTED_SCALE, roomMap.restrictedScale);
const dimensions = roomMap.dimensions;
if (dimensions) {
const minX = roomMap.dimensions.minX;
const maxX = roomMap.dimensions.maxX;
const minY = roomMap.dimensions.minY;
const maxY = roomMap.dimensions.maxY;
instance.model.setValue(RoomVariableEnum.ROOM_MIN_X, minX);
instance.model.setValue(RoomVariableEnum.ROOM_MAX_X, maxX);
instance.model.setValue(RoomVariableEnum.ROOM_MIN_Y, minY);
instance.model.setValue(RoomVariableEnum.ROOM_MAX_Y, maxY);
const seed = Math.trunc(minX * 423 + maxX * 671 + minY * 913 + maxY * 7509);
if (roomObject && roomObject.model) roomObject.model.setValue(RoomObjectVariable.ROOM_RANDOM_SEED, seed);
}
}
const logic = (roomObject && (roomObject.logic as RoomLogic)) || null;
if (logic) {
logic.initialize(roomMap);
if (floorType) {
logic.processUpdateMessage(new ObjectRoomUpdateMessage(ObjectRoomUpdateMessage.ROOM_FLOOR_UPDATE, floorType));
instance.model.setValue(RoomObjectVariable.ROOM_FLOOR_TYPE, floorType);
}
if (wallType) {
logic.processUpdateMessage(new ObjectRoomUpdateMessage(ObjectRoomUpdateMessage.ROOM_WALL_UPDATE, wallType));
instance.model.setValue(RoomObjectVariable.ROOM_WALL_TYPE, wallType);
}
if (landscapeType) {
logic.processUpdateMessage(new ObjectRoomUpdateMessage(ObjectRoomUpdateMessage.ROOM_LANDSCAPE_UPDATE, landscapeType));
instance.model.setValue(RoomObjectVariable.ROOM_LANDSCAPE_TYPE, landscapeType);
}
}
if (roomMap && roomMap.doors.length) {
let doorIndex = 0;
while (doorIndex < roomMap.doors.length) {
const door = roomMap.doors[doorIndex];
if (door) {
const doorX = door.x;
const doorY = door.y;
const doorZ = door.z;
const doorDir = door.dir;
const maskType = ObjectRoomMaskUpdateMessage.DOOR;
const maskId = "door_" + doorIndex;
const maskLocation = new Vector3d(doorX, doorY, doorZ);
logic.processUpdateMessage(
new ObjectRoomMaskUpdateMessage(ObjectRoomMaskUpdateMessage.ADD_MASK, maskId, maskType, maskLocation, ObjectRoomMaskUpdateMessage.HOLE)
);
if (doorDir === 90 || doorDir === 180) {
if (doorDir === 90) {
instance.model.setValue(RoomObjectVariable.ROOM_DOOR_X, doorX - 0.5);
instance.model.setValue(RoomObjectVariable.ROOM_DOOR_Y, doorY);
}
if (doorDir === 180) {
instance.model.setValue(RoomObjectVariable.ROOM_DOOR_X, doorX);
instance.model.setValue(RoomObjectVariable.ROOM_DOOR_Y, doorY - 0.5);
}
instance.model.setValue(RoomObjectVariable.ROOM_DOOR_Z, doorZ);
instance.model.setValue(RoomObjectVariable.ROOM_DOOR_DIR, doorDir);
}
}
doorIndex++;
}
}
instance.createRoomObjectAndInitalize(RoomEngine.CURSOR_OBJECT_ID, RoomEngine.CURSOR_OBJECT_TYPE, RoomObjectCategory.CURSOR);
if (NitroConfiguration.getValue("enable.avatar.arrow", false))
instance.createRoomObjectAndInitalize(RoomEngine.ARROW_OBJECT_ID, RoomEngine.ARROW_OBJECT_TYPE, RoomObjectCategory.CURSOR);
return instance;
}
public getRoomInstanceDisplay(roomId: number, id: number, width: number, height: number, scale: number): DisplayObject {
const instance = this.getRoomInstance(roomId);
if (!instance) return null;
let renderer = instance.renderer as IRoomRenderer;
if (!renderer) {
renderer = this._roomRendererFactory.createRenderer();
if (!renderer) return null;
}
renderer.roomObjectVariableAccurateZ = RoomObjectVariable.OBJECT_ACCURATE_Z_VALUE;
instance.setRenderer(renderer);
const canvas = renderer.createCanvas(id, width, height, scale);
if (!canvas) return null;
const restrictedScaling = instance.model.getValue<boolean>(RoomVariableEnum.RESTRICTS_SCALING);
if (restrictedScaling) {
let restrictedScale = instance.model.getValue<number>(RoomVariableEnum.RESTRICTED_SCALE);
if (!restrictedScale) restrictedScale = 1;
canvas.setScale(restrictedScale);
canvas.restrictsScaling = true;
} else {
canvas.restrictsScaling = false;
}
canvas.setMouseListener(this._roomObjectEventHandler);
if (canvas.geometry) {
canvas.geometry.z_scale = instance.model.getValue(RoomVariableEnum.ROOM_Z_SCALE);
const doorX = instance.model.getValue<number>(RoomObjectVariable.ROOM_DOOR_X);
const doorY = instance.model.getValue<number>(RoomObjectVariable.ROOM_DOOR_Y);
const doorZ = instance.model.getValue<number>(RoomObjectVariable.ROOM_DOOR_Z);
const doorDirection = instance.model.getValue<number>(RoomObjectVariable.ROOM_DOOR_DIR);
const vector = new Vector3d(doorX, doorY, doorZ);
let direction: IVector3D = null;
if (doorDirection === 90) direction = new Vector3d(-2000, 0, 0);
if (doorDirection === 180) direction = new Vector3d(0, -2000, 0);
canvas.geometry.setDisplacement(vector, direction);
const displayObject = canvas.master as Container;
if (displayObject) {
const overlay = new NitroSprite(Texture.EMPTY);
overlay.name = RoomEngine.OVERLAY;
overlay.interactive = false;
displayObject.addChild(overlay);
}
}
return canvas.master;
}
public setRoomInstanceRenderingCanvasMask(roomId: number, canvasId: number, flag: boolean): void {
const roomCanvas = this.getRoomInstanceRenderingCanvas(roomId, canvasId);
if (roomCanvas) roomCanvas.setMask(flag);
}
public setRoomInstanceRenderingCanvasScale(
roomId: number,
canvasId: number,
scale: number,
point: Point = null,
offsetPoint: Point = null,
override: boolean = false,
asDelta: boolean = false
): void {
const roomCanvas = this.getRoomInstanceRenderingCanvas(roomId, canvasId);
if (roomCanvas) {
if (roomCanvas.restrictsScaling && !override) return;
roomCanvas.setScale(scale, point, offsetPoint, override, asDelta);
this.events.dispatchEvent(new RoomEngineEvent(RoomEngineEvent.ROOM_ZOOMED, roomId));
}
}
public getRoomInstanceRenderingCanvas(roomId: number, canvasId: number = -1): IRoomRenderingCanvas {
const instance = this.getRoomInstance(roomId);
if (!instance) return null;
const renderer = instance.renderer as IRoomRenderer;
if (!renderer) return null;
if (canvasId === -1) canvasId = this._activeRoomActiveCanvas;
const canvas = renderer.getCanvas(canvasId);
if (!canvas) return null;
return canvas;
}
public getActiveRoomInstanceRenderingCanvas(): IRoomRenderingCanvas {
return this.getRoomInstanceRenderingCanvas(this._activeRoomId, this._activeRoomActiveCanvas);
}
public getRoomInstanceRenderingCanvasOffset(roomId: number, canvasId: number = -1): Point {
if (canvasId === -1) canvasId = this._activeRoomActiveCanvas;
const renderingCanvas = this.getRoomInstanceRenderingCanvas(roomId, canvasId);
if (!renderingCanvas) return null;
return new Point(renderingCanvas.screenOffsetX, renderingCanvas.screenOffsetY);
}
public setRoomInstanceRenderingCanvasOffset(roomId: number, canvasId: number, point: Point): boolean {
const renderingCanvas = this.getRoomInstanceRenderingCanvas(roomId, canvasId);
if (!renderingCanvas || !point) return false;
const x = ~~point.x;
const y = ~~point.y;
if (renderingCanvas.screenOffsetX === x && renderingCanvas.screenOffsetY === y) return false;
this.events.dispatchEvent(new RoomDragEvent(roomId, -(renderingCanvas.screenOffsetX - x), -(renderingCanvas.screenOffsetY - y)));
renderingCanvas.screenOffsetX = x;
renderingCanvas.screenOffsetY = y;
return true;
}
public getRoomInstanceRenderingCanvasScale(roomId: number = -1000, canvasId: number = -1): number {
if (roomId === -1000) roomId = this._activeRoomId;
if (canvasId === -1) canvasId = this._activeRoomActiveCanvas;
const canvas = this.getRoomInstanceRenderingCanvas(roomId, canvasId);
if (!canvas) return 1;
return canvas.scale;
}
public initializeRoomInstanceRenderingCanvas(roomId: number, canvasId: number, width: number, height: number): void {
const canvas = this.getRoomInstanceRenderingCanvas(roomId, canvasId);
if (!canvas) return;
canvas.initialize(width, height);
}
public getRoomInstanceGeometry(roomId: number, canvasId: number = -1): IRoomGeometry {
const instance = this.getRoomInstance(roomId);
if (!instance) return null;
const renderer = instance.renderer as IRoomRenderer;
if (!renderer) return null;
if (canvasId === -1) canvasId = this._activeRoomActiveCanvas;
const canvas = renderer.getCanvas(canvasId);
if (!canvas) return null;
return canvas.geometry;
}
public getRoomInstanceVariable<T>(roomId: number, key: string): T {
const instance = this.getRoomInstance(roomId);
if (!instance) return null;
return (instance.model && instance.model.getValue(key)) || null;
}
public updateRoomInstancePlaneVisibility(roomId: number, wallVisible: boolean, floorVisible: boolean = true): boolean {
const object = this.getRoomOwnObject(roomId);
if (!object) return false;
object.processUpdateMessage(new ObjectRoomPlaneVisibilityUpdateMessage(ObjectRoomPlaneVisibilityUpdateMessage.WALL_VISIBILITY, wallVisible));
object.processUpdateMessage(new ObjectRoomPlaneVisibilityUpdateMessage(ObjectRoomPlaneVisibilityUpdateMessage.FLOOR_VISIBILITY, floorVisible));
return true;
}
public updateRoomInstancePlaneThickness(roomId: number, wallThickness: number, floorThickness: number): boolean {
const object = this.getRoomOwnObject(roomId);
if (!object) return false;
object.processUpdateMessage(new ObjectRoomPlanePropertyUpdateMessage(ObjectRoomPlanePropertyUpdateMessage.WALL_THICKNESS, wallThickness));
object.processUpdateMessage(new ObjectRoomPlanePropertyUpdateMessage(ObjectRoomPlanePropertyUpdateMessage.FLOOR_THICKNESS, floorThickness));
return true;
}
public updateRoomInstancePlaneType(
roomId: number,
floorType: string = null,
wallType: string = null,
landscapeType: string = null,
_arg_5: boolean = false
): boolean {
const roomObject = this.getRoomOwnObject(roomId);
const roomInstance = this.getRoomInstance(roomId);
if (!roomObject) {
let roomData = this._roomDatas.get(roomId);
if (!roomData) {
roomData = new RoomData(roomId, null);
this._roomDatas.set(roomId, roomData);
}
if (floorType) roomData.floorType = floorType;
if (wallType) roomData.wallType = wallType;
if (landscapeType) roomData.landscapeType = landscapeType;
return true;
}
if (floorType) {
if (roomInstance && !_arg_5) roomInstance.model.setValue(RoomObjectVariable.ROOM_FLOOR_TYPE, floorType);
roomObject.processUpdateMessage(new ObjectRoomUpdateMessage(ObjectRoomUpdateMessage.ROOM_FLOOR_UPDATE, floorType));
}
if (wallType) {
if (roomInstance && !_arg_5) roomInstance.model.setValue(RoomObjectVariable.ROOM_WALL_TYPE, wallType);
roomObject.processUpdateMessage(new ObjectRoomUpdateMessage(ObjectRoomUpdateMessage.ROOM_WALL_UPDATE, wallType));
}
if (landscapeType) {
if (roomInstance && !_arg_5) roomInstance.model.setValue(RoomObjectVariable.ROOM_LANDSCAPE_TYPE, landscapeType);
roomObject.processUpdateMessage(new ObjectRoomUpdateMessage(ObjectRoomUpdateMessage.ROOM_LANDSCAPE_UPDATE, landscapeType));
}
return true;
}
public updateObjectRoomColor(roomId: number, color: number, light: number, backgroundOnly: boolean): boolean {
const roomObject = this.getRoomOwnObject(roomId);
if (!roomObject || !roomObject.logic) return false;
const event = new ObjectRoomColorUpdateMessage(ObjectRoomColorUpdateMessage.BACKGROUND_COLOR, color, light, backgroundOnly);
roomObject.logic.processUpdateMessage(event);
this.events.dispatchEvent(new RoomBackgroundColorEvent(roomId, color, light, backgroundOnly));
return true;
}
public addRoomInstanceFloorHole(roomId: number, objectId: number): void {
if (objectId < 0) return;
const roomOwnObject = this.getRoomOwnObject(roomId);
const roomObject = this.getRoomObjectFloor(roomId, objectId);
if (roomOwnObject && roomOwnObject.logic && roomObject && roomObject.model) {
const location = roomObject.getLocation();
const sizeX = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_SIZE_X);
const sizeY = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_SIZE_Y);
roomOwnObject.processUpdateMessage(
new ObjectRoomFloorHoleUpdateMessage(ObjectRoomFloorHoleUpdateMessage.ADD, objectId, location.x, location.y, sizeX, sizeY)
);
}
}
public removeRoomInstanceFloorHole(roomId: number, objectId: number): void {
if (objectId < 0) return;
const roomOwnObject = this.getRoomOwnObject(roomId);
if (roomOwnObject) {
roomOwnObject.processUpdateMessage(new ObjectRoomFloorHoleUpdateMessage(ObjectRoomFloorHoleUpdateMessage.REMOVE, objectId));
}
}
public setRoomEngineGameMode(roomId: number, isPlaying: boolean): void {
const roomInstance = this.getRoomInstance(roomId);
if (!roomInstance) return;
const mode = isPlaying ? 1 : 0;
roomInstance.model.setValue(RoomVariableEnum.IS_PLAYING_GAME, mode);
if (mode === 0) {
this.events.dispatchEvent(new RoomEngineEvent(RoomEngineEvent.NORMAL_MODE, roomId));
} else {
this.events.dispatchEvent(new RoomEngineEvent(RoomEngineEvent.GAME_MODE, roomId));
}
}
public isRoomIdPlayingGame(roomId: number): boolean {
const roomInstance = this.getRoomInstance(roomId);
if (!roomInstance) return false;
return roomInstance.model.getValue<number>(RoomVariableEnum.IS_PLAYING_GAME) > 0;
}
public isPlayingGame(): boolean {
return this.isRoomIdPlayingGame(this._activeRoomId);
}
public disableUpdate(flag: boolean): void {
if (flag) {
GetTicker().remove(this.update, this);
} else {
GetTicker().remove(this.update, this);
GetTicker().add(this.update, this);
}
}
public runUpdate(): void {
this.update(1);
}
public runVisibilityUpdate(): void {
if (!document.hidden) this.update(1, true);
}
public update(time: number, update: boolean = false): void {
if (!this._roomManager) return;
time = GetTickerTime();
RoomEnterEffect.turnVisualizationOn();
this.processPendingFurniture();
this._roomManager.update(time, update);
this.updateRoomCameras(time);
if (this._mouseCursorUpdate) this.setPointer();
RoomEnterEffect.turnVisualizationOff();
}
private setPointer(): void {
this._mouseCursorUpdate = false;
const instanceData = this.getRoomInstanceData(this._activeRoomId);
if (instanceData && instanceData.hasButtonMouseCursorOwners()) {
document.body.style.cursor = "pointer";
} else {
document.body.style.cursor = "auto";
}
}
private processPendingFurniture(): void {
if (this._skipFurnitureCreationForNextFrame) {
this._skipFurnitureCreationForNextFrame = false;
return;
}
const startTime = new Date().valueOf();
const furniturePerTick = 5;
const hasTickLimit = true;
for (const instanceData of this._roomInstanceDatas.values()) {
if (!instanceData) continue;
let pendingData: RoomFurnitureData = null;
let totalFurnitureAdded = 0;
let furnitureAdded = false;
while ((pendingData = instanceData.getNextPendingFurnitureFloor())) {
furnitureAdded = this.processPendingFurnitureFloor(instanceData.roomId, pendingData.id, pendingData);
if (hasTickLimit) {
if (!(++totalFurnitureAdded % furniturePerTick)) {
const time = new Date().valueOf();
if (time - startTime >= 40) {
this._skipFurnitureCreationForNextFrame = true;
break;
}
}
}
}
while (!this._skipFurnitureCreationForNextFrame && (pendingData = instanceData.getNextPendingFurnitureWall())) {
furnitureAdded = this.processPendingFurnitureWall(instanceData.roomId, pendingData.id, pendingData);
if (hasTickLimit) {
if (!(++totalFurnitureAdded % furniturePerTick)) {
const time = new Date().valueOf();
if (time - startTime >= 40) {
this._skipFurnitureCreationForNextFrame = true;
break;
}
}
}
}
if (furnitureAdded && this._roomManager) {
const roomInstance = this._roomManager.getRoomInstance(this.getRoomId(instanceData.roomId)) as RoomInstance;
if (!roomInstance.hasUninitializedObjects()) this.objectsInitialized(instanceData.roomId.toString());
}
if (this._skipFurnitureCreationForNextFrame) return;
}
}
public onRoomEngineInitalized(flag: boolean): void {
if (!flag) return;
this._ready = true;
this.events.dispatchEvent(new RoomEngineEvent(RoomEngineEvent.ENGINE_INITIALIZED, 0));
for (const roomData of this._roomDatas.values()) {
if (!roomData) continue;
this.createRoomInstance(roomData.roomId, roomData.data);
}
}
private processPendingFurnitureFloor(roomId: number, id: number, data: RoomFurnitureData): boolean {
if (!data) {
const instanceData = this.getRoomInstanceData(roomId);
if (instanceData) data = instanceData.getPendingFurnitureFloor(id);
if (!data) return false;
}
let type = data.type;
let didLoad = false;
if (!type) {
type = this.getFurnitureFloorName(data.typeId);
didLoad = true;
}
const object = this.createRoomObjectFloor(roomId, id, type);
if (!object) return false;
const model = object.model;
if (model) {
model.setValue(RoomObjectVariable.FURNITURE_COLOR, this.getFurnitureFloorColorIndex(data.typeId));
model.setValue(RoomObjectVariable.FURNITURE_TYPE_ID, data.typeId);
model.setValue(RoomObjectVariable.FURNITURE_AD_URL, this.getRoomObjectAdUrl(data.type));
model.setValue(RoomObjectVariable.FURNITURE_REAL_ROOM_OBJECT, data.realRoomObject ? 1 : 0);
model.setValue(RoomObjectVariable.FURNITURE_EXPIRY_TIME, data.expiryTime);
model.setValue(RoomObjectVariable.FURNITURE_EXPIRTY_TIMESTAMP, GetTickerTime());
model.setValue(RoomObjectVariable.FURNITURE_USAGE_POLICY, data.usagePolicy);
model.setValue(RoomObjectVariable.FURNITURE_OWNER_ID, data.ownerId);
model.setValue(RoomObjectVariable.FURNITURE_OWNER_NAME, data.ownerName);
}
if (!this.updateRoomObjectFloor(roomId, id, data.location, data.direction, data.state, data.data, data.extra)) return false;
if (data.sizeZ >= 0) {
if (!this.updateRoomObjectFloorHeight(roomId, id, data.sizeZ)) return false;
}
if (this.events) this.events.dispatchEvent(new RoomEngineObjectEvent(RoomEngineObjectEvent.ADDED, roomId, id, RoomObjectCategory.FLOOR));
const selectedRoomObjectData = this.getPlacedRoomObjectData(roomId);
if (selectedRoomObjectData && selectedRoomObjectData.id === id && selectedRoomObjectData.category === RoomObjectCategory.FLOOR) {
this.selectRoomObject(roomId, id, RoomObjectCategory.FLOOR);
}
if (object.isReady && data.synchronized) this.addObjectToTileMap(roomId, object);
return true;
}
private processPendingFurnitureWall(roomId: number, id: number, data: RoomFurnitureData): boolean {
if (!data) {
const instanceData = this.getRoomInstanceData(roomId);
if (instanceData) data = instanceData.getPendingFurnitureWall(id);
if (!data) return false;
}
let extra = "";
if (data.data) extra = data.data.getLegacyString();
let type = this.getFurnitureWallName(data.typeId, extra);
if (!type) type = "";
const object = this.createRoomObjectWall(roomId, id, type);
if (!object) return false;
const model = object.model;
if (model) {
model.setValue(RoomObjectVariable.FURNITURE_COLOR, this.getFurnitureWallColorIndex(data.typeId));
model.setValue(RoomObjectVariable.FURNITURE_TYPE_ID, data.typeId);
model.setValue(RoomObjectVariable.FURNITURE_AD_URL, this.getRoomObjectAdUrl(data.type));
model.setValue(RoomObjectVariable.FURNITURE_REAL_ROOM_OBJECT, data.realRoomObject ? 1 : 0);
model.setValue(RoomObjectVariable.OBJECT_ACCURATE_Z_VALUE, 1);
model.setValue(RoomObjectVariable.FURNITURE_EXPIRY_TIME, data.expiryTime);
model.setValue(RoomObjectVariable.FURNITURE_EXPIRTY_TIMESTAMP, GetTickerTime());
model.setValue(RoomObjectVariable.FURNITURE_USAGE_POLICY, data.usagePolicy);
model.setValue(RoomObjectVariable.FURNITURE_OWNER_ID, data.ownerId);
model.setValue(RoomObjectVariable.FURNITURE_OWNER_NAME, data.ownerName);
}
if (!this.updateRoomObjectWall(roomId, id, data.location, data.direction, data.state, extra)) return false;
if (this.events) this.events.dispatchEvent(new RoomEngineObjectEvent(RoomEngineObjectEvent.ADDED, roomId, id, RoomObjectCategory.WALL));
const selectedRoomObjectData = this.getPlacedRoomObjectData(roomId);
if (selectedRoomObjectData && Math.abs(selectedRoomObjectData.id) === id && selectedRoomObjectData.category === RoomObjectCategory.WALL) {
this.selectRoomObject(roomId, id, RoomObjectCategory.WALL);
}
return true;
}
public setRoomSessionOwnUser(roomId: number, objectId: number): void {
if (!this._roomSessionManager) return;
const session = this._roomSessionManager.getSession(roomId);
if (session) {
session.setOwnRoomIndex(objectId);
}
const camera = this.getRoomCamera(roomId);
if (camera) {
camera.targetId = objectId;
camera.targetCategory = RoomObjectCategory.UNIT;
camera.activateFollowing(this.cameraFollowDuration);
}
}
private get cameraFollowDuration(): number {
return 1000;
//return (getBoolean("room.camera.follow_user")) ? 1000 : 0;
}
private updateRoomCameras(time: number): void {
for (const instanceData of this._roomInstanceDatas.values()) {
if (!instanceData) continue;
const camera = instanceData.roomCamera;
if (!camera) continue;
let location: IVector3D = null;
const object = this.getRoomObject(instanceData.roomId, camera.targetId, camera.targetCategory);
if (object) location = object.getLocation();
if (!location) continue;
if (instanceData.roomId !== this._activeRoomId || !this._activeRoomIsDragged) {
this.updateRoomCamera(instanceData.roomId, 1, location, time);
}
}
if (this._activeRoomWasDragged) {
const renderingCanvas = this.getRoomInstanceRenderingCanvas(this._activeRoomId, 1);
if (renderingCanvas)
this.setRoomInstanceRenderingCanvasOffset(
this._activeRoomId,
1,
new Point(renderingCanvas.screenOffsetX + this._activeRoomDragX, renderingCanvas.screenOffsetY + this._activeRoomDragY)
);
this._activeRoomDragX = 0;
this._activeRoomDragY = 0;
}
}
private updateRoomCamera(roomId: number, canvasId: number, objectLocation: IVector3D, time: number): void {
const renderingCanvas = this.getRoomInstanceRenderingCanvas(roomId, canvasId);
const instanceData = this.getRoomInstanceData(roomId);
if (!renderingCanvas || !instanceData || renderingCanvas.scale !== 1) return;
const roomGeometry = renderingCanvas.geometry as RoomGeometry;
const roomCamera = instanceData.roomCamera;
const roomInstance = this.getRoomInstance(roomId);
if (!roomGeometry || !roomCamera || !roomInstance) return;
const canvasRectangle = this.getRoomCanvasRectangle(roomId, canvasId);
if (!canvasRectangle) return;
let _local_10 = Math.floor(objectLocation.z) + 1;
const width = Math.round(canvasRectangle.width);
const height = Math.round(canvasRectangle.height);
const bounds = this.getCanvasBoundingRectangle(canvasId);
if (bounds && (bounds.right < 0 || bounds.bottom < 0 || bounds.left >= width || bounds.top >= height)) {
roomCamera.reset();
}
if (
roomCamera.screenWd !== width ||
roomCamera.screenHt !== height ||
roomCamera.scale !== roomGeometry.scale ||
roomCamera.geometryUpdateId !== roomGeometry.updateId ||
!Vector3d.isEqual(objectLocation, roomCamera.targetObjectLoc) ||
roomCamera.isMoving
) {
roomCamera.targetObjectLoc = objectLocation;
const _local_15 = new Vector3d();
_local_15.assign(objectLocation);
_local_15.x = Math.round(_local_15.x);
_local_15.y = Math.round(_local_15.y);
const _local_16 = roomInstance.model.getValue<number>(RoomVariableEnum.ROOM_MIN_X) - 0.5;
const _local_17 = roomInstance.model.getValue<number>(RoomVariableEnum.ROOM_MIN_Y) - 0.5;
const _local_18 = roomInstance.model.getValue<number>(RoomVariableEnum.ROOM_MAX_X) + 0.5;
const _local_19 = roomInstance.model.getValue<number>(RoomVariableEnum.ROOM_MAX_Y) + 0.5;
const _local_20 = Math.round((_local_16 + _local_18) / 2);
const _local_21 = Math.round((_local_17 + _local_19) / 2);
const _local_22 = 2;
let _local_23 = new Point(_local_15.x - _local_20, _local_15.y - _local_21);
const _local_24 = roomGeometry.scale / Math.sqrt(2);
const _local_25 = _local_24 / 2;
const _local_26 = new Matrix();
_local_26.rotate((-(roomGeometry.direction.x + 90) / 180) * Math.PI);
_local_23 = _local_26.apply(_local_23);
_local_23.y = _local_23.y * (_local_25 / _local_24);
const _local_27 = canvasRectangle.width / 2 / _local_24 - 1;
const _local_28 = canvasRectangle.height / 2 / _local_25 - 1;
let _local_29 = 0;
let _local_30 = 0;
let _local_31 = 0;
let _local_32 = 0;
let _local_33 = roomGeometry.getScreenPoint(new Vector3d(_local_20, _local_21, _local_22));
if (!_local_33) return;
_local_33.x = _local_33.x + Math.round(canvasRectangle.width / 2);
_local_33.y = _local_33.y + Math.round(canvasRectangle.height / 2);
if (bounds) {
bounds.x += -renderingCanvas.screenOffsetX;
bounds.y += -renderingCanvas.screenOffsetY;
if (bounds.width > 1 && bounds.height > 1) {
_local_29 = (bounds.left - _local_33.x - roomGeometry.scale * 0.25) / _local_24;
_local_31 = (bounds.right - _local_33.x + roomGeometry.scale * 0.25) / _local_24;
_local_30 = (bounds.top - _local_33.y - roomGeometry.scale * 0.5) / _local_25;
_local_32 = (bounds.bottom - _local_33.y + roomGeometry.scale * 0.5) / _local_25;
} else {
roomGeometry.adjustLocation(new Vector3d(-30, -30), 25);
return;
}
} else {
roomGeometry.adjustLocation(new Vector3d(0, 0), 25);
return;
}
let _local_34 = false;
let _local_35 = false;
let _local_36 = false;
let _local_37 = false;
const _local_38 = Math.round((_local_31 - _local_29) * _local_24);
if (_local_38 < canvasRectangle.width) {
_local_10 = 2;
_local_23.x = (_local_31 + _local_29) / 2;
_local_36 = true;
} else {
if (_local_23.x > _local_31 - _local_27) {
_local_23.x = _local_31 - _local_27;
_local_34 = true;
}
if (_local_23.x < _local_29 + _local_27) {
_local_23.x = _local_29 + _local_27;
_local_34 = true;
}
}
const _local_39 = Math.round((_local_32 - _local_30) * _local_25);
if (_local_39 < canvasRectangle.height) {
_local_10 = 2;
_local_23.y = (_local_32 + _local_30) / 2;
_local_37 = true;
} else {
if (_local_23.y > _local_32 - _local_28) {
_local_23.y = _local_32 - _local_28;
_local_35 = true;
}
if (_local_23.y < _local_30 + _local_28) {
_local_23.y = _local_30 + _local_28;
_local_35 = true;
}
if (_local_35) {
_local_23.y = _local_23.y / (_local_25 / _local_24);
}
}
_local_26.invert();
_local_23 = _local_26.apply(_local_23);
_local_23.x = _local_23.x + _local_20;
_local_23.y = _local_23.y + _local_21;
let _local_40 = 0.35;
let _local_41 = 0.2;
let _local_42 = 0.2;
const _local_43 = 10;
const _local_44 = 10;
if (_local_42 * width > 100) {
_local_42 = 100 / width;
}
if (_local_40 * height > 150) {
_local_40 = 150 / height;
}
if (_local_41 * height > 150) {
_local_41 = 150 / height;
}
if (roomCamera.limitedLocationX && roomCamera.screenWd == width && roomCamera.screenHt == height) {
_local_42 = 0;
}
if (roomCamera.limitedLocationY && roomCamera.screenWd == width && roomCamera.screenHt == height) {
_local_40 = 0;
_local_41 = 0;
}
canvasRectangle.width = canvasRectangle.width * (1 - _local_42 * 2);
canvasRectangle.height = canvasRectangle.height * (1 - (_local_40 + _local_41));
if (canvasRectangle.width < _local_43) {
canvasRectangle.width = _local_43;
}
if (canvasRectangle.height < _local_44) {
canvasRectangle.height = _local_44;
}
if (_local_40 + _local_41 > 0) {
canvasRectangle.x += -canvasRectangle.width / 2;
canvasRectangle.y += -canvasRectangle.height * (_local_41 / (_local_40 + _local_41));
} else {
canvasRectangle.x += -canvasRectangle.width / 2;
canvasRectangle.y += -canvasRectangle.height / 2;
}
_local_33 = roomGeometry.getScreenPoint(_local_15);
if (!_local_33) return;
if (_local_33) {
_local_33.x = _local_33.x + renderingCanvas.screenOffsetX;
_local_33.y = _local_33.y + renderingCanvas.screenOffsetY;
_local_15.z = _local_10;
_local_15.x = Math.round(_local_23.x * 2) / 2;
_local_15.y = Math.round(_local_23.y * 2) / 2;
if (!roomCamera.location) {
roomGeometry.location = _local_15;
if (this.useOffsetScrolling) {
roomCamera.initializeLocation(new Vector3d(0, 0, 0));
} else {
roomCamera.initializeLocation(_local_15);
}
}
const _local_45 = roomGeometry.getScreenPoint(_local_15);
const _local_46 = new Vector3d(0, 0, 0);
if (_local_45) {
_local_46.x = _local_45.x;
_local_46.y = _local_45.y;
}
if (
((_local_33.x < canvasRectangle.left || _local_33.x > canvasRectangle.right) && !roomCamera.centeredLocX) ||
((_local_33.y < canvasRectangle.top || _local_33.y > canvasRectangle.bottom) && !roomCamera.centeredLocY) ||
(_local_36 && !roomCamera.centeredLocX && !(roomCamera.screenWd == width)) ||
(_local_37 && !roomCamera.centeredLocY && !(roomCamera.screenHt == height)) ||
!(roomCamera.roomWd == bounds.width) ||
!(roomCamera.roomHt == bounds.height) ||
!(roomCamera.screenWd == width) ||
!(roomCamera.screenHt == height)
) {
roomCamera.limitedLocationX = _local_34;
roomCamera.limitedLocationY = _local_35;
if (this.useOffsetScrolling) {
roomCamera.target = _local_46;
} else {
roomCamera.target = _local_15;
}
} else {
if (!_local_34) roomCamera.limitedLocationX = false;
if (!_local_35) roomCamera.limitedLocationY = false;
}
}
roomCamera.centeredLocX = _local_36;
roomCamera.centeredLocY = _local_37;
roomCamera.screenWd = width;
roomCamera.screenHt = height;
roomCamera.scale = roomGeometry.scale;
roomCamera.geometryUpdateId = roomGeometry.updateId;
roomCamera.roomWd = bounds.width;
roomCamera.roomHt = bounds.height;
if (!this._sessionDataManager.isCameraFollowDisabled) {
if (this.useOffsetScrolling) {
roomCamera.update(time, 8);
} else {
roomCamera.update(time, 0.5);
}
}
if (this.useOffsetScrolling) {
this.setRoomInstanceRenderingCanvasOffset(this.activeRoomId, 1, new Point(-roomCamera.location.x, -roomCamera.location.y));
} else {
roomGeometry.adjustLocation(roomCamera.location, 25);
}
} else {
roomCamera.limitedLocationX = false;
roomCamera.limitedLocationY = false;
roomCamera.centeredLocX = false;
roomCamera.centeredLocY = false;
}
}
private getRoomCanvasRectangle(roomId: number, canvasId: number): Rectangle {
const canvas = this.getRoomInstanceRenderingCanvas(roomId, canvasId);
if (!canvas) return null;
return new Rectangle(0, 0, canvas.width, canvas.height);
}
public getRoomObjectBoundingRectangle(roomId: number, objectId: number, category: number, canvasId: number): Rectangle {
const geometry = this.getRoomInstanceGeometry(roomId, canvasId);
if (!geometry) return null;
const roomObject = this.getRoomObject(roomId, objectId, category);
if (!roomObject) return null;
const visualization = roomObject.visualization;
if (!visualization) return null;
const rectangle = visualization.getBoundingRectangle();
const canvas = this.getRoomInstanceRenderingCanvas(roomId, canvasId);
const scale = canvas ? canvas.scale : 1;
const screenPoint = geometry.getScreenPoint(roomObject.getLocation());
if (!screenPoint) return null;
screenPoint.x = Math.round(screenPoint.x);
screenPoint.y = Math.round(screenPoint.y);
rectangle.x = rectangle.x * scale;
rectangle.y = rectangle.y * scale;
rectangle.width = rectangle.width * scale;
rectangle.height = rectangle.height * scale;
screenPoint.x = screenPoint.x * scale;
screenPoint.y = screenPoint.y * scale;
rectangle.x += screenPoint.x;
rectangle.y += screenPoint.y;
if (!canvas) return null;
rectangle.x += Math.round(canvas.width / 2) + canvas.screenOffsetX;
rectangle.y += Math.round(canvas.height / 2) + canvas.screenOffsetY;
return rectangle;
}
public getCanvasBoundingRectangle(canvasId: number): Rectangle {
return this.getRoomObjectBoundingRectangle(this._activeRoomId, RoomEngine.ROOM_OBJECT_ID, RoomObjectCategory.ROOM, canvasId);
}
public getFurnitureFloorName(typeId: number): string {
if (!this._roomContentLoader) return null;
return this._roomContentLoader.getFurnitureFloorNameForTypeId(typeId);
}
public getFurnitureWallName(typeId: number, extra: string = null): string {
if (!this._roomContentLoader) return null;
return this._roomContentLoader.getFurnitureWallNameForTypeId(typeId, extra);
}
public getFurnitureFloorColorIndex(typeId: number): number {
if (!this._roomContentLoader) return null;
return this._roomContentLoader.getFurnitureFloorColorIndex(typeId);
}
public getFurnitureWallColorIndex(typeId: number): number {
if (!this._roomContentLoader) return null;
return this._roomContentLoader.getFurnitureWallColorIndex(typeId);
}
private getRoomInstanceData(roomId: number): RoomInstanceData {
const existing = this._roomInstanceDatas.get(roomId);
if (existing) return existing;
const data = new RoomInstanceData(roomId);
this._roomInstanceDatas.set(data.roomId, data);
return data;
}
public getRoomInstanceModelName(roomId: number): string {
const instanceData = this.getRoomInstanceData(roomId);
if (!instanceData) return null;
return instanceData.modelName;
}
public setRoomInstanceModelName(roomId: number, name: string): void {
const instanceData = this.getRoomInstanceData(roomId);
if (!instanceData) return;
instanceData.setModelName(name);
}
public getRoomTileObjectMap(k: number): ITileObjectMap {
const roomInstance = this.getRoomInstanceData(k);
if (!roomInstance) return null;
return roomInstance.tileObjectMap;
}
private getCurrentRoomCamera(): RoomCamera {
return this.getRoomCamera(this._activeRoomId);
}
private getRoomCamera(roomId: number): RoomCamera {
const instanceData = this.getRoomInstanceData(roomId);
if (!instanceData) return null;
return instanceData.roomCamera;
}
public getSelectedRoomObjectData(roomId: number): ISelectedRoomObjectData {
const instanceData = this.getRoomInstanceData(roomId);
if (!instanceData) return null;
return instanceData.selectedObject;
}
public setSelectedRoomObjectData(roomId: number, data: ISelectedRoomObjectData): void {
const instanceData = this.getRoomInstanceData(roomId);
if (!instanceData) return null;
instanceData.setSelectedObject(data);
if (data) instanceData.setPlacedObject(null);
}
public getPlacedRoomObjectData(roomId: number): ISelectedRoomObjectData {
const instanceData = this.getRoomInstanceData(roomId);
if (!instanceData) return null;
return instanceData.placedObject;
}
public setPlacedRoomObjectData(roomId: number, data: ISelectedRoomObjectData): void {
const instanceData = this.getRoomInstanceData(roomId);
if (!instanceData) return null;
instanceData.setPlacedObject(data);
}
public cancelRoomObjectPlacement(): void {
if (!this._roomObjectEventHandler) return;
this._roomObjectEventHandler.cancelRoomObjectPlacement(this._activeRoomId);
}
public getFurnitureStackingHeightMap(roomId: number): IFurnitureStackingHeightMap {
const instanceData = this.getRoomInstanceData(roomId);
if (!instanceData) return null;
return instanceData.furnitureStackingHeightMap;
}
public setFurnitureStackingHeightMap(roomId: number, heightMap: IFurnitureStackingHeightMap): void {
const instanceData = this.getRoomInstanceData(roomId);
if (!instanceData) return null;
instanceData.setFurnitureStackingHeightMap(heightMap);
}
public getLegacyWallGeometry(roomId: number): ILegacyWallGeometry {
const instanceData = this.getRoomInstanceData(roomId);
if (!instanceData) return null;
return instanceData.legacyGeometry;
}
private createRoomObjectAndInitialize(roomId: number, objectId: number, type: string, category: number): IRoomObjectController {
const instance = this.getRoomInstance(roomId);
if (!instance) return null;
return instance.createRoomObjectAndInitalize(objectId, type, category) as IRoomObjectController;
}
public getTotalObjectsForManager(roomId: number, category: number): number {
const instance = this.getRoomInstance(roomId);
if (!instance) return 0;
return instance.getTotalObjectsForManager(category);
}
public getRoomObject(roomId: number, objectId: number, category: number): IRoomObjectController {
if (!this._ready) return null;
let roomIdString = this.getRoomId(roomId);
if (roomId === 0) roomIdString = RoomEngine.TEMPORARY_ROOM;
return this.getObject(roomIdString, objectId, category);
}
public getObject(roomId: string, objectId: number, category: number): IRoomObjectController {
let roomInstance: IRoomInstance = null;
if (this._roomManager) roomInstance = this._roomManager.getRoomInstance(roomId);
if (!roomInstance) return null;
let roomObject = roomInstance.getRoomObject(objectId, category) as IRoomObjectController;
if (!roomObject) {
switch (category) {
case RoomObjectCategory.FLOOR:
this.processPendingFurnitureFloor(this.getRoomIdFromString(roomId), objectId, null);
roomObject = roomInstance.getRoomObject(objectId, category) as IRoomObjectController;
break;
case RoomObjectCategory.WALL:
this.processPendingFurnitureWall(this.getRoomIdFromString(roomId), objectId, null);
roomObject = roomInstance.getRoomObject(objectId, category) as IRoomObjectController;
break;
}
}
return roomObject;
}
public getRoomObjectByIndex(roomId: number, index: number, category: number): IRoomObjectController {
const instance = this.getRoomInstance(roomId);
if (!instance) return null;
return instance.getRoomObjectByIndex(index, category) as IRoomObjectController;
}
public getRoomObjectCategoryForType(type: string): number {
if (!type || !this._roomContentLoader) return RoomObjectCategory.MINIMUM;
return this._roomContentLoader.getCategoryForType(type);
}
public getRoomObjectCursor(roomId: number): IRoomObjectController {
return this.getObject(this.getRoomId(roomId), RoomEngine.CURSOR_OBJECT_ID, RoomObjectCategory.CURSOR);
}
public getRoomObjectSelectionArrow(roomId: number): IRoomObjectController {
return this.getObject(this.getRoomId(roomId), RoomEngine.ARROW_OBJECT_ID, RoomObjectCategory.CURSOR);
}
public getRoomOwnObject(roomId: number): IRoomObjectController {
return this.getObject(this.getRoomId(roomId), RoomEngine.ROOM_OBJECT_ID, RoomObjectCategory.ROOM);
}
public getRoomObjectUser(roomId: number, objectId: number): IRoomObjectController {
return this.getObject(this.getRoomId(roomId), objectId, RoomObjectCategory.UNIT);
}
public removeRoomObjectUser(roomId: number, objectId: number): void {
return this.removeRoomObject(roomId, objectId, RoomObjectCategory.UNIT);
}
public createRoomObjectUser(roomId: number, objectId: number, type: string): IRoomObjectController {
return this.createRoomObjectAndInitialize(roomId, objectId, type, RoomObjectCategory.UNIT);
}
public getRoomObjectFloor(roomId: number, objectId: number): IRoomObjectController {
return this.getObject(this.getRoomId(roomId), objectId, RoomObjectCategory.FLOOR);
}
public createRoomObjectFloor(roomId: number, id: number, type: string): IRoomObjectController {
return this.createRoomObjectAndInitialize(roomId, id, type, RoomObjectCategory.FLOOR);
}
public removeRoomObjectFloor(roomId: number, objectId: number, userId: number = -1, _arg_4: boolean = false): void {
const roomInstanceData = this.getRoomInstanceData(roomId);
if (roomInstanceData) roomInstanceData.removePendingFunitureFloor(objectId);
if (this._sessionDataManager && userId === this._sessionDataManager.userId && !FurniId.isBuilderClubId(objectId)) {
const roomObject = this.getRoomObject(roomId, objectId, RoomObjectCategory.FLOOR);
if (roomObject) {
const screenLocation = this.getRoomObjectScreenLocation(roomId, objectId, RoomObjectCategory.FLOOR, this._activeRoomActiveCanvas);
if (screenLocation) {
const disabledPickingAnimation = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_DISABLE_PICKING_ANIMATION) === 1;
if (!disabledPickingAnimation) {
const typeId = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_TYPE_ID);
const extras = roomObject.model.getValue<string>(RoomObjectVariable.FURNITURE_EXTRAS);
const dataKey = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_DATA_FORMAT);
const objectData = ObjectDataFactory.getData(dataKey);
const icon = this.getFurnitureFloorIcon(typeId, null, extras, objectData).data;
if (icon) {
const image = TextureUtils.generateImage(icon);
if (this.events) {
const event = new NitroToolbarAnimateIconEvent(image, screenLocation.x, screenLocation.y);
event.iconName = ToolbarIconEnum.INVENTORY;
this.events.dispatchEvent(event);
}
}
}
}
}
}
this.removeRoomObject(roomId, objectId, RoomObjectCategory.FLOOR);
this.setMouseDefault(roomId, RoomObjectCategory.FLOOR, objectId);
if (_arg_4) this.refreshTileObjectMap(roomId, "RoomEngine.disposeObjectFurniture()");
}
public getRoomObjectWall(roomId: number, objectId: number): IRoomObjectController {
return this.getObject(this.getRoomId(roomId), objectId, RoomObjectCategory.WALL);
}
public removeRoomObjectWall(roomId: number, objectId: number, userId: number = -1): void {
if (this._sessionDataManager && userId === this._sessionDataManager.userId && !FurniId.isBuilderClubId(objectId)) {
const roomObject = this.getRoomObject(roomId, objectId, RoomObjectCategory.WALL);
if (roomObject && roomObject.type.indexOf("post_it") === -1 && roomObject.type.indexOf("external_image_wallitem") === -1) {
const screenLocation = this.getRoomObjectScreenLocation(roomId, objectId, RoomObjectCategory.WALL, this._activeRoomActiveCanvas);
if (screenLocation) {
const typeId = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_TYPE_ID);
const objectData = roomObject.model.getValue<string>(RoomObjectVariable.FURNITURE_DATA);
const icon = this.getFurnitureWallIcon(typeId, null, objectData).data;
if (icon) {
const image = TextureUtils.generateImage(icon);
if (this.events) {
const event = new NitroToolbarAnimateIconEvent(image, screenLocation.x, screenLocation.y);
event.iconName = ToolbarIconEnum.INVENTORY;
this.events.dispatchEvent(event);
}
}
}
}
}
this.removeRoomObject(roomId, objectId, RoomObjectCategory.WALL);
this.updateRoomObjectMask(roomId, objectId, false);
this.setMouseDefault(roomId, RoomObjectCategory.WALL, objectId);
}
public createRoomObjectWall(roomId: number, id: number, type: string): IRoomObjectController {
return this.createRoomObjectAndInitialize(roomId, id, type, RoomObjectCategory.WALL);
}
private removeRoomObject(roomId: number, objectId: number, category: number): void {
const instance = this.getRoomInstance(roomId);
if (!instance) return null;
instance.removeRoomObject(objectId, category);
if (this.events) this.events.dispatchEvent(new RoomEngineObjectEvent(RoomEngineObjectEvent.REMOVED, roomId, objectId, category));
}
public addFurnitureFloor(
roomId: number,
id: number,
typeId: number,
location: IVector3D,
direction: IVector3D,
state: number,
objectData: IObjectData,
extra: number = NaN,
expires: number = -1,
usagePolicy: number = 0,
ownerId: number = 0,
ownerName: string = "",
synchronized: boolean = true,
realRoomObject: boolean = true,
sizeZ: number = -1
): boolean {
const instanceData = this.getRoomInstanceData(roomId);
if (!instanceData) return false;
const furnitureData = new RoomFurnitureData(
id,
typeId,
null,
location,
direction,
state,
objectData,
extra,
expires,
usagePolicy,
ownerId,
ownerName,
synchronized,
realRoomObject,
sizeZ
);
instanceData.addPendingFurnitureFloor(furnitureData);
return true;
}
public addFurnitureFloorByTypeName(
roomId: number,
id: number,
typeName: string,
location: IVector3D,
direction: IVector3D,
state: number,
objectData: IObjectData,
extra: number = NaN,
expires: number = -1,
usagePolicy: number = 0,
ownerId: number = 0,
ownerName: string = "",
synchronized: boolean = true,
realRoomObject: boolean = true,
sizeZ: number = -1
): boolean {
const instanceData = this.getRoomInstanceData(roomId);
if (!instanceData) return false;
const furnitureData = new RoomFurnitureData(
id,
0,
typeName,
location,
direction,
state,
objectData,
extra,
expires,
usagePolicy,
ownerId,
ownerName,
synchronized,
realRoomObject,
sizeZ
);
instanceData.addPendingFurnitureFloor(furnitureData);
return true;
}
public addFurnitureWall(
roomId: number,
id: number,
typeId: number,
location: IVector3D,
direction: IVector3D,
state: number,
extra: string,
expires: number = -1,
usagePolicy: number = 0,
ownerId: number = 0,
ownerName: string = "",
realRoomObject: boolean = true
): boolean {
const instanceData = this.getRoomInstanceData(roomId);
if (!instanceData) return false;
const objectData = new LegacyDataType();
objectData.setString(extra);
const furnitureData = new RoomFurnitureData(
id,
typeId,
null,
location,
direction,
state,
objectData,
NaN,
expires,
usagePolicy,
ownerId,
ownerName,
true,
realRoomObject
);
instanceData.addPendingFurnitureWall(furnitureData);
return true;
}
public updateRoomObjectFloor(
roomId: number,
objectId: number,
location: IVector3D,
direction: IVector3D,
state: number,
data: IObjectData,
extra: number = null
): boolean {
const object = this.getRoomObjectFloor(roomId, objectId);
if (!object) return false;
object.processUpdateMessage(new RoomObjectUpdateMessage(location, direction));
object.processUpdateMessage(new ObjectDataUpdateMessage(state, data, extra));
return true;
}
public updateRoomObjectWall(roomId: number, objectId: number, location: IVector3D, direction: IVector3D, state: number, extra: string = null): boolean {
const object = this.getRoomObjectWall(roomId, objectId);
if (!object || !object.logic) return false;
const updateMessage = new RoomObjectUpdateMessage(location, direction);
const data = new LegacyDataType();
const dataUpdateMessage = new ObjectDataUpdateMessage(state, data);
data.setString(extra);
object.logic.processUpdateMessage(updateMessage);
object.logic.processUpdateMessage(dataUpdateMessage);
this.updateRoomObjectMask(roomId, objectId);
return true;
}
public updateRoomObjectWallItemData(roomId: number, objectId: number, data: string): boolean {
const object = this.getRoomObjectWall(roomId, objectId);
if (!object || !object.logic) return false;
object.logic.processUpdateMessage(new ObjectItemDataUpdateMessage(data));
return true;
}
public updateRoomObjectFloorHeight(roomId: number, objectId: number, height: number): boolean {
const object = this.getRoomObjectFloor(roomId, objectId);
if (!object) return false;
object.processUpdateMessage(new ObjectHeightUpdateMessage(null, null, height));
return true;
}
public updateRoomObjectFloorExpiration(roomId: number, objectId: number, expires: number): boolean {
const object = this.getRoomObjectFloor(roomId, objectId);
if (!object) return false;
object.model.setValue(RoomObjectVariable.FURNITURE_EXPIRY_TIME, expires);
object.model.setValue(RoomObjectVariable.FURNITURE_EXPIRTY_TIMESTAMP, GetTickerTime());
return true;
}
public updateRoomObjectWallExpiration(roomId: number, objectId: number, expires: number): boolean {
const object = this.getRoomObjectWall(roomId, objectId);
if (!object) return false;
object.model.setValue(RoomObjectVariable.FURNITURE_EXPIRY_TIME, expires);
object.model.setValue(RoomObjectVariable.FURNITURE_EXPIRTY_TIMESTAMP, GetTickerTime());
return true;
}
public updateRoomObjectMask(roomId: number, objectId: number, _arg_3: boolean = true): void {
const maskName = RoomObjectCategory.WALL + "_" + objectId;
const roomObject = this.getRoomObjectWall(roomId, objectId);
let maskUpdate: ObjectRoomMaskUpdateMessage = null;
if (roomObject && roomObject.model) {
if (roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_USES_PLANE_MASK) > 0) {
const maskType = roomObject.model.getValue<string>(RoomObjectVariable.FURNITURE_PLANE_MASK_TYPE);
const location = roomObject.getLocation();
if (_arg_3) maskUpdate = new ObjectRoomMaskUpdateMessage(ObjectRoomMaskUpdateMessage.ADD_MASK, maskName, maskType, location);
else maskUpdate = new ObjectRoomMaskUpdateMessage(ObjectRoomMaskUpdateMessage.REMOVE_MASK, maskName);
}
} else {
maskUpdate = new ObjectRoomMaskUpdateMessage(ObjectRoomMaskUpdateMessage.REMOVE_MASK, maskName);
}
const roomOwnObject = this.getRoomOwnObject(roomId);
if (roomOwnObject && roomOwnObject.logic && maskUpdate) roomOwnObject.logic.processUpdateMessage(maskUpdate);
}
public rollRoomObjectFloor(roomId: number, objectId: number, location: IVector3D, targetLocation: IVector3D): void {
const object = this.getRoomObjectFloor(roomId, objectId);
if (!object) return;
object.processUpdateMessage(new ObjectMoveUpdateMessage(location, targetLocation, null, !!targetLocation));
}
public updateRoomObjectWallLocation(roomId: number, objectId: number, location: IVector3D): boolean {
const roomObject = this.getRoomObjectWall(roomId, objectId);
if (!roomObject) return false;
if (roomObject.logic) roomObject.logic.processUpdateMessage(new ObjectMoveUpdateMessage(location, null, null));
this.updateRoomObjectMask(roomId, objectId);
return true;
}
public addRoomObjectUser(
roomId: number,
objectId: number,
location: IVector3D,
direction: IVector3D,
headDirection: number,
type: number,
figure: string
): boolean {
const existing = this.getRoomObjectUser(roomId, objectId);
if (existing) return false;
let objectType = RoomObjectUserType.getTypeString(type);
if (objectType === RoomObjectUserType.PET) objectType = this.getPetType(figure);
const object = this.createRoomObjectUser(roomId, objectId, objectType);
if (!object) return false;
//object.model.setValue(RoomObjectVariable.FIGURE_HIGHLIGHT_ENABLE, 1);
object.processUpdateMessage(new ObjectAvatarUpdateMessage(this.fixedUserLocation(roomId, location), null, direction, headDirection, false, 0));
if (figure) object.processUpdateMessage(new ObjectAvatarFigureUpdateMessage(figure));
if (this.events) this.events.dispatchEvent(new RoomEngineObjectEvent(RoomEngineObjectEvent.ADDED, roomId, objectId, RoomObjectCategory.UNIT));
return true;
}
public updateRoomObjectUserLocation(
roomId: number,
objectId: number,
location: IVector3D,
targetLocation: IVector3D,
canStandUp: boolean = false,
baseY: number = 0,
direction: IVector3D = null,
headDirection: number = NaN
): boolean {
const object = this.getRoomObjectUser(roomId, objectId);
if (!object) return false;
if (!location) location = object.getLocation();
if (!direction) direction = object.getDirection();
if (isNaN(headDirection)) headDirection = object.model.getValue<number>(RoomObjectVariable.HEAD_DIRECTION);
object.processUpdateMessage(
new ObjectAvatarUpdateMessage(
this.fixedUserLocation(roomId, location),
this.fixedUserLocation(roomId, targetLocation),
direction,
headDirection,
canStandUp,
baseY
)
);
const roomSession = (this._roomSessionManager && this._roomSessionManager.getSession(roomId)) || null;
if (roomSession && roomSession.ownRoomIndex === objectId) {
this._logicFactory.events.dispatchEvent(new RoomToObjectOwnAvatarMoveEvent(RoomToObjectOwnAvatarMoveEvent.ROAME_MOVE_TO, targetLocation));
}
return true;
}
private fixedUserLocation(roomId: number, location: IVector3D): IVector3D {
if (!location) return null;
const heightMap = this.getFurnitureStackingHeightMap(roomId);
const wallGeometry = this.getLegacyWallGeometry(roomId);
if (!heightMap || !wallGeometry) return location;
let _local_5 = location.z;
const _local_6 = heightMap.getTileHeight(location.x, location.y);
const _local_7 = wallGeometry.getHeight(location.x, location.y);
if (Math.abs(_local_5 - _local_6) < 0.1 && Math.abs(_local_6 - _local_7) < 0.1) {
_local_5 = wallGeometry.getFloorAltitude(location.x, location.y);
}
return new Vector3d(location.x, location.y, _local_5);
}
public updateRoomObjectUserAction(roomId: number, objectId: number, action: string, value: number, parameter: string = null): boolean {
const object = this.getRoomObjectUser(roomId, objectId);
if (!object) return false;
let message: ObjectStateUpdateMessage = null;
switch (action) {
case RoomObjectVariable.FIGURE_TALK:
message = new ObjectAvatarChatUpdateMessage(value);
break;
case RoomObjectVariable.FIGURE_SLEEP:
message = new ObjectAvatarSleepUpdateMessage(value === 1);
break;
case RoomObjectVariable.FIGURE_IS_TYPING:
message = new ObjectAvatarTypingUpdateMessage(value === 1);
break;
case RoomObjectVariable.FIGURE_IS_MUTED:
message = new ObjectAvatarMutedUpdateMessage(value === 1);
break;
case RoomObjectVariable.FIGURE_CARRY_OBJECT:
message = new ObjectAvatarCarryObjectUpdateMessage(value, parameter);
break;
case RoomObjectVariable.FIGURE_USE_OBJECT:
message = new ObjectAvatarUseObjectUpdateMessage(value);
break;
case RoomObjectVariable.FIGURE_DANCE:
message = new ObjectAvatarDanceUpdateMessage(value);
break;
case RoomObjectVariable.FIGURE_GAINED_EXPERIENCE:
message = new ObjectAvatarExperienceUpdateMessage(value);
break;
case RoomObjectVariable.FIGURE_NUMBER_VALUE:
message = new ObjectAvatarPlayerValueUpdateMessage(value);
break;
case RoomObjectVariable.FIGURE_SIGN:
message = new ObjectAvatarSignUpdateMessage(value);
break;
case RoomObjectVariable.FIGURE_EXPRESSION:
message = new ObjectAvatarExpressionUpdateMessage(value);
break;
case RoomObjectVariable.FIGURE_IS_PLAYING_GAME:
message = new ObjectAvatarPlayingGameUpdateMessage(value === 1);
break;
case RoomObjectVariable.FIGURE_GUIDE_STATUS:
message = new ObjectAvatarGuideStatusUpdateMessage(value);
break;
}
if (!message) return false;
object.processUpdateMessage(message);
return true;
}
public updateRoomObjectUserFigure(
roomId: number,
objectId: number,
figure: string,
gender: string = null,
subType: string = null,
isRiding: boolean = false
): boolean {
const object = this.getRoomObjectUser(roomId, objectId);
if (!object) return false;
object.processUpdateMessage(new ObjectAvatarFigureUpdateMessage(figure, gender, subType, isRiding));
return true;
}
public updateRoomObjectUserFlatControl(roomId: number, objectId: number, level: string): boolean {
const object = this.getRoomObjectUser(roomId, objectId);
if (!object) return false;
object.processUpdateMessage(new ObjectAvatarFlatControlUpdateMessage(parseInt(level)));
return true;
}
public updateRoomObjectUserEffect(roomId: number, objectId: number, effectId: number, delay: number = 0): boolean {
const object = this.getRoomObjectUser(roomId, objectId);
if (!object) return false;
object.processUpdateMessage(new ObjectAvatarEffectUpdateMessage(effectId, delay));
return true;
}
public updateRoomObjectUserGesture(roomId: number, objectId: number, gestureId: number): boolean {
const object = this.getRoomObjectUser(roomId, objectId);
if (!object) return false;
object.processUpdateMessage(new ObjectAvatarGestureUpdateMessage(gestureId));
return true;
}
public updateRoomObjectUserPetGesture(roomId: number, objectId: number, gesture: string): boolean {
const object = this.getRoomObjectUser(roomId, objectId);
if (!object) return false;
object.processUpdateMessage(new ObjectAvatarPetGestureUpdateMessage(gesture));
return true;
}
public updateRoomObjectUserPosture(roomId: number, objectId: number, type: string, parameter: string = null): boolean {
const object = this.getRoomObjectUser(roomId, objectId);
if (!object) return false;
object.processUpdateMessage(new ObjectAvatarPostureUpdateMessage(type, parameter));
return true;
}
public updateRoomObjectUserOwn(roomId: number, objectId: number): void {
const object = this.getRoomObjectUser(roomId, objectId);
if (!object) return;
object.processUpdateMessage(new ObjectAvatarOwnMessage());
}
public useRoomObject(objectId: number, category: number): boolean {
const roomObject = this.getRoomObject(this._activeRoomId, objectId, category);
if (roomObject) {
const eventHandler = roomObject.logic;
if (eventHandler) {
eventHandler.useObject();
return true;
}
}
return false;
}
public objectInitialized(roomId: string, objectId: number, category: number): void {
const id = this.getRoomIdFromString(roomId);
if (category === RoomObjectCategory.WALL) {
this.updateRoomObjectMask(id, objectId);
}
const object = this.getRoomObject(id, objectId, category);
if (object && object.model && object.logic) {
const dataFormat = object.model.getValue<number>(RoomObjectVariable.FURNITURE_DATA_FORMAT);
if (!isNaN(dataFormat)) {
const data = ObjectDataFactory.getData(dataFormat);
data.initializeFromRoomObjectModel(object.model);
object.processUpdateMessage(new ObjectDataUpdateMessage(object.getState(0), data));
}
this.events.dispatchEvent(new RoomEngineObjectEvent(RoomEngineObjectEvent.CONTENT_UPDATED, id, objectId, category));
}
if (roomId !== RoomEngine.TEMPORARY_ROOM) this.addObjectToTileMap(id, object);
}
public changeObjectModelData(roomId: number, objectId: number, category: number, numberKey: string, numberValue: number): boolean {
const roomObject = this.getObject(this.getRoomId(roomId), objectId, category);
if (!roomObject || !roomObject.logic) return false;
const message = new ObjectModelDataUpdateMessage(numberKey, numberValue);
roomObject.processUpdateMessage(message);
return true;
}
public changeObjectState(roomId: number, objectId: number, category: number): void {
const roomObject = this.getObject(this.getRoomId(roomId), objectId, category);
if (!roomObject || !roomObject.model) return;
let stateIndex = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_AUTOMATIC_STATE_INDEX);
if (isNaN(stateIndex)) stateIndex = 1;
else stateIndex = stateIndex + 1;
roomObject.model.setValue(RoomObjectVariable.FURNITURE_AUTOMATIC_STATE_INDEX, stateIndex);
const objectDataKey = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_DATA_FORMAT);
const objectData = ObjectDataFactory.getData(objectDataKey);
objectData.initializeFromRoomObjectModel(roomObject.model);
if (roomObject.logic) roomObject.logic.processUpdateMessage(new ObjectDataUpdateMessage(stateIndex, objectData));
}
public loadRoomObjectBadgeImage(roomId: number, objectId: number, objectCategory: number, badgeId: string, groupBadge: boolean = true): void {
if (!this._sessionDataManager) return;
let roomObject: IRoomObjectController = null;
if (roomId === 0) {
const room = this._roomManager.getRoomInstance(RoomEngine.TEMPORARY_ROOM);
if (room) roomObject = room.getRoomObject(objectId, objectCategory) as IRoomObjectController;
} else {
roomObject = this.getRoomObjectFloor(roomId, objectId);
}
if (!roomObject || !roomObject.logic) return;
let badgeName = groupBadge ? this._sessionDataManager.loadGroupBadgeImage(badgeId) : this._sessionDataManager.loadBadgeImage(badgeId);
if (!badgeName) {
badgeName = "loading_icon";
if (!this._badgeListenerObjects) this._badgeListenerObjects = new Map();
if (!this._badgeListenerObjects.size) {
this._sessionDataManager.events.addEventListener(BadgeImageReadyEvent.IMAGE_READY, this.onBadgeImageReadyEvent);
}
let listeners = this._badgeListenerObjects.get(badgeId);
if (!listeners) listeners = [];
listeners.push(new RoomObjectBadgeImageAssetListener(roomObject, groupBadge));
this._badgeListenerObjects.set(badgeId, listeners);
} else {
this.putBadgeInObjectAssets(roomObject, badgeId, groupBadge);
}
roomObject.logic.processUpdateMessage(new ObjectGroupBadgeUpdateMessage(badgeId, badgeName));
}
private onBadgeImageReadyEvent(k: BadgeImageReadyEvent): void {
if (!this._sessionDataManager) return;
const listeners = this._badgeListenerObjects && this._badgeListenerObjects.get(k.badgeId);
if (!listeners) return;
for (const listener of listeners) {
if (!listener) continue;
this.putBadgeInObjectAssets(listener.object, k.badgeId, listener.groupBadge);
const badgeName = listener.groupBadge ? this._sessionDataManager.loadGroupBadgeImage(k.badgeId) : this._sessionDataManager.loadBadgeImage(k.badgeId);
if (listener.object && listener.object.logic) listener.object.logic.processUpdateMessage(new ObjectGroupBadgeUpdateMessage(k.badgeId, badgeName));
}
this._badgeListenerObjects.delete(k.badgeId);
if (!this._badgeListenerObjects.size) {
this._sessionDataManager.events.removeEventListener(BadgeImageReadyEvent.IMAGE_READY, this.onBadgeImageReadyEvent);
}
}
private putBadgeInObjectAssets(object: IRoomObjectController, badgeId: string, groupBadge: boolean = false): void {
if (!this._roomContentLoader || !this._sessionDataManager) return;
const badgeName = groupBadge ? this._sessionDataManager.loadGroupBadgeImage(badgeId) : this._sessionDataManager.loadBadgeImage(badgeId);
const badgeImage = groupBadge ? this._sessionDataManager.getGroupBadgeImage(badgeId) : this._sessionDataManager.getBadgeImage(badgeId);
if (badgeImage) this._roomContentLoader.addAssetToCollection(object.type, badgeName, badgeImage, false);
}
public dispatchMouseEvent(
canvasId: number,
x: number,
y: number,
type: string,
altKey: boolean,
ctrlKey: boolean,
shiftKey: boolean,
buttonDown: boolean
): void {
const canvas = this.getRoomInstanceRenderingCanvas(this._activeRoomId, canvasId);
if (!canvas) return;
const overlay = this.getRenderingCanvasOverlay(canvas);
const sprite = this.getOverlayIconSprite(overlay, RoomEngine.OBJECT_ICON_SPRITE);
if (sprite) {
const rectangle = sprite.getLocalBounds();
sprite.x = x - rectangle.width / 2;
sprite.y = y - rectangle.height / 2;
}
if (!this.handleRoomDragging(canvas, x, y, type, altKey, ctrlKey, shiftKey)) {
if (!canvas.handleMouseEvent(x, y, type, altKey, ctrlKey, shiftKey, buttonDown)) {
let eventType: string = null;
if (type === MouseEventType.MOUSE_CLICK) {
if (this.events) {
this.events.dispatchEvent(new RoomEngineObjectEvent(RoomEngineObjectEvent.DESELECTED, this._activeRoomId, -1, RoomObjectCategory.MINIMUM));
}
eventType = RoomObjectMouseEvent.CLICK;
} else {
if (type === MouseEventType.MOUSE_MOVE) eventType = RoomObjectMouseEvent.MOUSE_MOVE;
else if (type === MouseEventType.MOUSE_DOWN) eventType = RoomObjectMouseEvent.MOUSE_DOWN;
else if (type === MouseEventType.MOUSE_DOWN_LONG) eventType = RoomObjectMouseEvent.MOUSE_DOWN_LONG;
else if (type === MouseEventType.MOUSE_UP) eventType = RoomObjectMouseEvent.MOUSE_UP;
}
this._roomObjectEventHandler.handleRoomObjectEvent(
new RoomObjectMouseEvent(eventType, this.getRoomObject(this._activeRoomId, RoomEngine.ROOM_OBJECT_ID, RoomObjectCategory.ROOM), null, altKey),
this._activeRoomId
);
}
}
this._activeRoomActiveCanvas = canvasId;
this._activeRoomActiveCanvasMouseX = x;
this._activeRoomActiveCanvasMouseY = y;
}
private handleRoomDragging(canvas: IRoomRenderingCanvas, x: number, y: number, type: string, altKey: boolean, ctrlKey: boolean, shiftKey: boolean): boolean {
let offsetX = x - this._activeRoomActiveCanvasMouseX;
let offsetY = y - this._activeRoomActiveCanvasMouseY;
if (type === MouseEventType.MOUSE_DOWN) {
if (!altKey && !ctrlKey && !shiftKey && !this.isDecorating) {
if (this._roomAllowsDragging) {
this._activeRoomIsDragged = true;
this._activeRoomWasDragged = false;
this._activeRoomDragStartX = this._activeRoomActiveCanvasMouseX;
this._activeRoomDragStartY = this._activeRoomActiveCanvasMouseY;
}
}
} else if (type === MouseEventType.MOUSE_UP) {
if (this._activeRoomIsDragged) {
this._activeRoomIsDragged = false;
if (this._activeRoomWasDragged) {
const instanceData = this.getRoomInstanceData(this._activeRoomId);
if (instanceData) {
const camera = instanceData.roomCamera;
if (camera) {
if (this.useOffsetScrolling) {
if (!camera.isMoving) {
camera.centeredLocX = false;
camera.centeredLocY = false;
}
camera.resetLocation(new Vector3d(-canvas.screenOffsetX, -canvas.screenOffsetY));
}
if (this._roomDraggingAlwaysCenters) camera.reset();
}
}
}
}
} else if (type === MouseEventType.MOUSE_MOVE) {
if (this._activeRoomIsDragged) {
if (!this._activeRoomWasDragged) {
offsetX = x - this._activeRoomDragStartX;
offsetY = y - this._activeRoomDragStartY;
if (
offsetX <= -RoomEngine.DRAG_THRESHOLD ||
offsetX >= RoomEngine.DRAG_THRESHOLD ||
offsetY <= -RoomEngine.DRAG_THRESHOLD ||
offsetY >= RoomEngine.DRAG_THRESHOLD
) {
this._activeRoomWasDragged = true;
}
offsetX = 0;
offsetY = 0;
}
if (!(offsetX == 0) || !(offsetY == 0)) {
this._activeRoomDragX += offsetX;
this._activeRoomDragY += offsetY;
this._activeRoomWasDragged = true;
}
}
} else if (type === MouseEventType.MOUSE_CLICK || type === MouseEventType.DOUBLE_CLICK) {
this._activeRoomIsDragged = false;
if (this._activeRoomWasDragged) {
this._activeRoomWasDragged = false;
return true;
}
}
return false;
}
public updateMousePointer(type: string, objectId: number, objectType: string): void {
const category = this.getRoomObjectCategoryForType(objectType);
switch (type) {
case RoomObjectFurnitureActionEvent.MOUSE_BUTTON:
this.setMouseButton(this._activeRoomId, category, objectId);
return;
default:
this.setMouseDefault(this._activeRoomId, category, objectId);
return;
}
}
private setMouseButton(roomId: number, category: number, objectId: number): void {
if (!this._roomSessionManager) return;
const session = this._roomSessionManager.getSession(roomId);
if (!session) return;
if ((category !== RoomObjectCategory.FLOOR && category !== RoomObjectCategory.WALL) || session.controllerLevel >= RoomControllerLevel.GUEST) {
const instanceData = this.getRoomInstanceData(roomId);
if (instanceData) {
if (instanceData.addButtonMouseCursorOwner(category + "_" + objectId)) this._mouseCursorUpdate = true;
}
}
}
private setMouseDefault(roomId: number, category: number, objectId: number): void {
if (!this._roomSessionManager) return;
const instanceData = this.getRoomInstanceData(roomId);
if (instanceData) {
if (instanceData.removeButtonMouseCursorOwner(category + "_" + objectId)) this._mouseCursorUpdate = true;
}
}
public processRoomObjectOperation(objectId: number, category: number, operation: string): boolean {
if (!this._roomObjectEventHandler) return false;
this._roomObjectEventHandler.modifyRoomObject(this._activeRoomId, objectId, category, operation);
return true;
}
public modifyRoomObjectDataWithMap(objectId: number, category: number, operation: string, data: Map<string, string>): boolean {
if (!this._roomObjectEventHandler) return false;
if (category !== RoomObjectCategory.FLOOR) return false;
this._roomObjectEventHandler.modifyRoomObjectDataWithMap(this._activeRoomId, objectId, category, operation, data);
return true;
}
public modifyRoomObjectData(objectId: number, category: number, colorHex: string, data: string): boolean {
if (!this._roomObjectEventHandler) return false;
if (category !== RoomObjectCategory.WALL) return false;
this._roomObjectEventHandler.modifyWallItemData(this._activeRoomId, objectId, colorHex, data);
return true;
}
private processRoomObjectEvent(event: RoomObjectEvent): void {
if (!this._roomObjectEventHandler) return;
const roomIdString = this.getRoomObjectRoomId(event.object);
if (!roomIdString) return;
const roomId = this.getRoomIdFromString(roomIdString);
this._roomObjectEventHandler.handleRoomObjectEvent(event, roomId);
}
public processRoomObjectPlacement(
placementSource: string,
id: number,
category: number,
typeId: number,
extra: string = null,
stuffData: IObjectData = null,
state: number = -1,
frameNumber: number = -1,
posture: string = null
): boolean {
const roomInstance = this.getRoomInstance(this._activeRoomId);
if (!roomInstance || roomInstance.model.getValue<number>(RoomVariableEnum.ROOM_IS_PUBLIC) !== 0) return false;
if (!this._roomObjectEventHandler) return false;
return this._roomObjectEventHandler.processRoomObjectPlacement(
placementSource,
this._activeRoomId,
id,
category,
typeId,
extra,
stuffData,
state,
frameNumber,
posture
);
}
public getRoomObjectScreenLocation(roomId: number, objectId: number, objectType: number, canvasId: number = -1): Point {
if (canvasId == -1) canvasId = this._activeRoomActiveCanvas;
const geometry = this.getRoomInstanceGeometry(roomId, canvasId);
if (!geometry) return null;
const roomObject = this.getRoomObject(roomId, objectId, objectType);
if (!roomObject) return null;
const screenPoint = geometry.getScreenPoint(roomObject.getLocation());
if (!screenPoint) return null;
const renderingCanvas = this.getRoomInstanceRenderingCanvas(roomId, canvasId);
if (!renderingCanvas) return null;
screenPoint.x = screenPoint.x * renderingCanvas.scale;
screenPoint.y = screenPoint.y * renderingCanvas.scale;
screenPoint.x += renderingCanvas.width / 2 + renderingCanvas.screenOffsetX;
screenPoint.y += renderingCanvas.height / 2 + renderingCanvas.screenOffsetY;
screenPoint.x = Math.round(screenPoint.x);
screenPoint.y = Math.round(screenPoint.y);
return screenPoint;
}
public selectRoomObject(roomId: number, objectId: number, objectCategory: number): void {
if (!this._roomObjectEventHandler) return;
this._roomObjectEventHandler.setSelectedObject(roomId, objectId, objectCategory);
}
public setSelectedAvatar(roomId: number, objectId: number): void {
if (this._roomObjectEventHandler) return;
this._roomObjectEventHandler.setSelectedAvatar(roomId, objectId, true);
}
public cancelRoomObjectInsert(): void {
if (!this._roomObjectEventHandler) return;
this._roomObjectEventHandler.cancelRoomObjectInsert(this._activeRoomId);
}
private addOverlayIconSprite(k: NitroSprite, _arg_2: string, _arg_3: Texture<Resource>, scale: number = 1): NitroSprite {
if (!k || !_arg_3) return null;
let sprite = this.getOverlayIconSprite(k, _arg_2);
if (sprite) return null;
sprite = new NitroSprite(_arg_3);
sprite.name = _arg_2;
sprite.scale.set(scale);
k.addChild(sprite);
return sprite;
}
public onRoomContentLoaded(id: number, assetName: string, success: boolean): void {
if (!this._roomContentLoader || id === -1) return;
this._thumbnailObjectIdBank.freeNumber(id - 1);
const listeners = this._thumbnailCallbacks.get(assetName);
if (listeners) {
this._thumbnailCallbacks.delete(assetName);
const image = this._roomContentLoader.getImage(assetName);
if (image) {
for (const listener of listeners) {
if (!listener) continue;
listener.imageReady(id, null, image);
}
}
}
}
public setObjectMoverIconSprite(
objectId: number,
category: number,
_arg_3: boolean,
instanceData: string = null,
stuffData: IObjectData = null,
state: number = -1,
frameNumber: number = -1,
posture: string = null
): void {
let type: string = null;
let colorIndex = 0;
let imageResult: IImageResult = null;
const scale = 1;
if (_arg_3) {
imageResult = this.getRoomObjectImage(this._activeRoomId, objectId, category, new Vector3d(), 1, null);
} else {
if (this._roomContentLoader) {
if (category === RoomObjectCategory.FLOOR) {
type = this._roomContentLoader.getFurnitureFloorNameForTypeId(objectId);
colorIndex = this._roomContentLoader.getFurnitureFloorColorIndex(objectId);
} else if (category === RoomObjectCategory.WALL) {
type = this._roomContentLoader.getFurnitureWallNameForTypeId(objectId, instanceData);
colorIndex = this._roomContentLoader.getFurnitureWallColorIndex(objectId);
}
if (category === RoomObjectCategory.UNIT) {
type = RoomObjectUserType.getTypeString(objectId);
if (type === "pet") {
type = this.getPetType(instanceData);
const petFigureData = new PetFigureData(instanceData);
imageResult = this.getRoomObjectPetImage(
petFigureData.typeId,
petFigureData.paletteId,
petFigureData.color,
new Vector3d(180),
64,
null,
true,
0,
petFigureData.customParts,
posture
);
} else {
imageResult = this.getGenericRoomObjectImage(type, instanceData, new Vector3d(180), 64, null, 0, null, stuffData, state, frameNumber, posture);
}
} else {
imageResult = this.getGenericRoomObjectImage(
type,
colorIndex.toString(),
new Vector3d(),
1,
null,
0,
instanceData,
stuffData,
state,
frameNumber,
posture
);
}
}
}
if (!imageResult || !imageResult.data) return;
const canvas = this.getActiveRoomInstanceRenderingCanvas();
if (!canvas) return;
const overlay = this.getRenderingCanvasOverlay(canvas);
this.removeOverlayIconSprite(overlay, RoomEngine.OBJECT_ICON_SPRITE);
const _local_15 = this.addOverlayIconSprite(overlay, RoomEngine.OBJECT_ICON_SPRITE, imageResult.data, scale);
if (_local_15) {
_local_15.x = this._activeRoomActiveCanvasMouseX - imageResult.data.width / 2;
_local_15.y = this._activeRoomActiveCanvasMouseY - imageResult.data.height / 2;
}
}
public getRoomObjectImage(
roomId: number,
objectId: number,
category: number,
direction: IVector3D,
scale: number,
listener: IGetImageListener,
bgColor: number = 0
): IImageResult {
if (!this._roomManager) return null;
let id = -1;
let type: string = null;
let data: IObjectData = null;
let color = "";
let extras: string = null;
const roomIdString = this.getRoomId(roomId);
const roomInstance = this._roomManager.getRoomInstance(roomIdString);
if (roomInstance) {
const roomObject = roomInstance.getRoomObject(objectId, category);
if (roomObject && roomObject.model) {
id = roomObject.id;
type = roomObject.type;
switch (category) {
case RoomObjectCategory.FLOOR:
case RoomObjectCategory.WALL: {
color = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_COLOR).toString();
extras = roomObject.model.getValue<string>(RoomObjectVariable.FURNITURE_EXTRAS);
const dataFormat = roomObject.model.getValue<number>(RoomObjectVariable.FURNITURE_DATA_FORMAT);
if (dataFormat !== LegacyDataType.FORMAT_KEY) {
data = ObjectDataFactory.getData(dataFormat);
data.initializeFromRoomObjectModel(roomObject.model);
}
break;
}
case RoomObjectCategory.UNIT:
color = roomObject.model.getValue<string>(RoomObjectVariable.FIGURE);
break;
}
}
}
return this.getGenericRoomObjectImage(type, color, direction, scale, listener, bgColor, extras, data, -1, -1, null, id);
}
public getFurnitureFloorIconUrl(typeId: number): string {
let type: string = null;
let color = "";
if (this._roomContentLoader) {
type = this._roomContentLoader.getFurnitureFloorNameForTypeId(typeId);
color = this._roomContentLoader.getFurnitureFloorColorIndex(typeId).toString();
return this._roomContentLoader.getAssetIconUrl(type, color);
}
return null;
}
public getFurnitureFloorIcon(typeId: number, listener: IGetImageListener, extras: string = null, objectData: IObjectData = null): IImageResult {
return this.getFurnitureFloorImage(typeId, new Vector3d(), 1, listener, 0, extras, -1, -1, objectData);
}
public getFurnitureWallIconUrl(typeId: number, extra: string = null): string {
let type: string = null;
let color = "";
if (this._roomContentLoader) {
type = this._roomContentLoader.getFurnitureWallNameForTypeId(typeId, extra);
color = this._roomContentLoader.getFurnitureWallColorIndex(typeId).toString();
return this._roomContentLoader.getAssetIconUrl(type, color);
}
return null;
}
public getFurnitureWallIcon(typeId: number, listener: IGetImageListener, extras: string = null): IImageResult {
return this.getFurnitureWallImage(typeId, new Vector3d(), 1, listener, 0, extras);
}
public getFurnitureFloorImage(
typeId: number,
direction: IVector3D,
scale: number,
listener: IGetImageListener,
bgColor: number = 0,
extras: string = null,
state: number = -1,
frameCount: number = -1,
objectData: IObjectData = null
): IImageResult {
let type: string = null;
let color = "";
if (this._roomContentLoader) {
type = this._roomContentLoader.getFurnitureFloorNameForTypeId(typeId);
color = this._roomContentLoader.getFurnitureFloorColorIndex(typeId).toString();
}
if (scale === 1 && listener) {
return this.getGenericRoomObjectThumbnail(type, color, listener, extras, objectData);
}
return this.getGenericRoomObjectImage(type, color, direction, scale, listener, bgColor, extras, objectData, state, frameCount);
}
public getFurnitureWallImage(
typeId: number,
direction: IVector3D,
scale: number,
listener: IGetImageListener,
bgColor: number = 0,
extras: string = null,
state: number = -1,
frameCount: number = -1
): IImageResult {
let type: string = null;
let color = "";
if (this._roomContentLoader) {
type = this._roomContentLoader.getFurnitureWallNameForTypeId(typeId);
color = this._roomContentLoader.getFurnitureWallColorIndex(typeId).toString();
}
if (scale === 1 && listener) {
return this.getGenericRoomObjectThumbnail(type, color, listener, extras, null);
}
return this.getGenericRoomObjectImage(type, color, direction, scale, listener, bgColor, extras, null, state, frameCount);
}
public getRoomObjectPetImage(
typeId: number,
paletteId: number,
color: number,
direction: IVector3D,
scale: number,
listener: IGetImageListener,
headOnly: boolean = false,
bgColor: number = 0,
customParts: IPetCustomPart[] = null,
posture: string = null
): IImageResult {
let type: string = null;
let value = typeId + " " + paletteId + " " + color.toString(16);
if (headOnly) value = value + (" " + "head");
if (customParts) {
value = value + (" " + customParts.length);
for (const _local_13 of customParts) {
value = value + (" " + _local_13.layerId + " " + _local_13.partId + " " + _local_13.paletteId);
}
}
if (this._roomContentLoader) type = this._roomContentLoader.getPetNameForType(typeId);
return this.getGenericRoomObjectImage(type, value, direction, scale, listener, bgColor, null, null, -1, -1, posture);
}
public getGenericRoomObjectImage(
type: string,
value: string,
direction: IVector3D,
scale: number,
listener: IGetImageListener,
bgColor: number = 0,
extras: string = null,
objectData: IObjectData = null,
state: number = -1,
frameCount: number = -1,
posture: string = null,
originalId: number = -1
): IImageResult {
if (!this._roomManager) return null;
const imageResult = new ImageResult();
imageResult.id = -1;
if (!this._ready || !type) return imageResult;
let roomInstance = this._roomManager.getRoomInstance(RoomEngine.TEMPORARY_ROOM);
if (!roomInstance) {
roomInstance = this._roomManager.createRoomInstance(RoomEngine.TEMPORARY_ROOM);
if (!roomInstance) return imageResult;
}
let objectId = this._imageObjectIdBank.reserveNumber();
const objectCategory = this.getRoomObjectCategoryForType(type);
if (objectId < 0) return imageResult;
objectId++;
const roomObject = roomInstance.createRoomObjectAndInitalize(objectId, type, objectCategory) as IRoomObjectController;
if (!roomObject || !roomObject.model || !roomObject.logic) return imageResult;
const model = roomObject.model;
switch (objectCategory) {
case RoomObjectCategory.FLOOR:
case RoomObjectCategory.WALL:
model.setValue(RoomObjectVariable.FURNITURE_COLOR, parseInt(value));
model.setValue(RoomObjectVariable.FURNITURE_EXTRAS, extras);
break;
case RoomObjectCategory.UNIT:
if (
type === RoomObjectUserType.USER ||
type === RoomObjectUserType.BOT ||
type === RoomObjectUserType.RENTABLE_BOT ||
type === RoomObjectUserType.PET
) {
model.setValue(RoomObjectVariable.FIGURE, value);
} else {
const figureData = new PetFigureData(value);
model.setValue(RoomObjectVariable.PET_PALETTE_INDEX, figureData.paletteId);
model.setValue(RoomObjectVariable.PET_COLOR, figureData.color);
if (figureData.headOnly) model.setValue(RoomObjectVariable.PET_HEAD_ONLY, 1);
if (figureData.hasCustomParts) {
model.setValue(RoomObjectVariable.PET_CUSTOM_LAYER_IDS, figureData.customLayerIds);
model.setValue(RoomObjectVariable.PET_CUSTOM_PARTS_IDS, figureData.customPartIds);
model.setValue(RoomObjectVariable.PET_CUSTOM_PALETTE_IDS, figureData.customPaletteIds);
}
if (posture) model.setValue(RoomObjectVariable.FIGURE_POSTURE, posture);
}
break;
case RoomObjectCategory.ROOM:
break;
}
roomObject.setDirection(direction);
const visualization = roomObject.visualization;
if (!visualization) {
roomInstance.removeRoomObject(objectId, objectCategory);
return imageResult;
}
if (state > -1 || objectData) {
if (objectData && objectData.getLegacyString() !== "") {
roomObject.logic.processUpdateMessage(new ObjectDataUpdateMessage(parseInt(objectData.getLegacyString()), objectData));
} else {
roomObject.logic.processUpdateMessage(new ObjectDataUpdateMessage(state, objectData));
}
}
const geometry = new RoomGeometry(scale, new Vector3d(-135, 30, 0), new Vector3d(11, 11, 5));
visualization.update(geometry, 0, true, false);
if (frameCount > 0) {
let i = 0;
while (i < frameCount) {
visualization.update(geometry, 0, true, false);
i++;
}
}
const texture = visualization.getImage(bgColor, originalId);
imageResult.data = texture;
imageResult.id = objectId;
if (!this.isRoomContentTypeLoaded(type) && listener) {
let imageListeners = this._imageCallbacks.get(objectId.toString());
if (!imageListeners) {
imageListeners = [];
this._imageCallbacks.set(objectId.toString(), imageListeners);
}
imageListeners.push(listener);
model.setValue(RoomObjectVariable.IMAGE_QUERY_SCALE, scale);
} else {
roomInstance.removeRoomObject(objectId, objectCategory);
this._imageObjectIdBank.freeNumber(objectId - 1);
imageResult.id = 0;
}
geometry.dispose();
return imageResult;
}
public getGenericRoomObjectThumbnail(
type: string,
param: string,
listener: IGetImageListener,
extraData: string = null,
stuffData: IObjectData = null
): IImageResult {
if (!this._roomManager) return null;
const imageResult = new ImageResult();
imageResult.id = -1;
if (!this._ready || !type) return imageResult;
let roomInstance = this._roomManager.getRoomInstance(RoomEngine.TEMPORARY_ROOM);
if (!roomInstance) {
roomInstance = this._roomManager.createRoomInstance(RoomEngine.TEMPORARY_ROOM);
if (!roomInstance) return imageResult;
}
let objectId = this._thumbnailObjectIdBank.reserveNumber();
const objectCategory = this.getRoomObjectCategoryForType(type);
if (objectId < 0) return imageResult;
objectId++;
imageResult.id = objectId;
imageResult.data = null;
imageResult.image = null;
const assetName = [type, param].join("_");
const asset = this._roomContentLoader.getImage(assetName);
if (!asset && listener) {
let contentListeners = this._thumbnailCallbacks.get(assetName);
if (!contentListeners) {
contentListeners = [];
this._thumbnailCallbacks.set(assetName, contentListeners);
this._roomContentLoader.downloadImage(objectId, type, param, null);
}
contentListeners.push(listener);
} else {
if (asset) {
imageResult.image = asset;
}
this._thumbnailObjectIdBank.freeNumber(objectId - 1);
imageResult.id = 0;
}
return imageResult;
}
public initalizeTemporaryObjectsByType(type: string, _arg_2: boolean): void {
const roomInstance = this._roomManager.getRoomInstance(RoomEngine.TEMPORARY_ROOM);
if (!roomInstance || !this._roomContentLoader) return;
const objectCategory = this._roomContentLoader.getCategoryForType(type);
const objectManager = roomInstance.getManager(objectCategory);
let geometry: RoomGeometry = null;
let scale = 0;
if (objectManager && objectManager.objects.length) {
for (const roomObject of objectManager.objects.getValues()) {
if (roomObject && roomObject.model && roomObject.type === type) {
const objectId = roomObject.id;
const visualization = roomObject.visualization;
let texture: RenderTexture = null;
if (visualization) {
const imageScale = roomObject.model.getValue<number>(RoomObjectVariable.IMAGE_QUERY_SCALE);
if (geometry && scale !== imageScale) {
geometry.dispose();
geometry = null;
}
if (!geometry) {
scale = imageScale;
geometry = new RoomGeometry(imageScale, new Vector3d(-135, 30, 0), new Vector3d(11, 11, 5));
}
visualization.update(geometry, 0, true, false);
texture = visualization.image;
}
roomInstance.removeRoomObject(objectId, objectCategory);
this._imageObjectIdBank.freeNumber(objectId - 1);
const imageListeners = this._imageCallbacks.get(objectId.toString());
if (imageListeners) {
this._imageCallbacks.delete(objectId.toString());
for (const imageListener of imageListeners) {
if (!imageListener) continue;
if (texture) imageListener.imageReady(objectId, texture);
else imageListener.imageFailed(objectId);
}
}
}
}
}
if (geometry) geometry.dispose();
}
public setObjectMoverIconSpriteVisible(k: boolean): void {
const canvas = this.getActiveRoomInstanceRenderingCanvas();
if (!canvas) return;
const overlay = this.getRenderingCanvasOverlay(canvas);
const sprite = this.getOverlayIconSprite(overlay, RoomEngine.OBJECT_ICON_SPRITE);
if (sprite) {
sprite.visible = k;
}
}
public removeObjectMoverIconSprite(): void {
const canvas = this.getActiveRoomInstanceRenderingCanvas();
if (!canvas) return;
const sprite = this.getRenderingCanvasOverlay(canvas);
this.removeOverlayIconSprite(sprite, RoomEngine.OBJECT_ICON_SPRITE);
}
private getRenderingCanvasOverlay(k: IRoomRenderingCanvas): NitroSprite {
if (!k) return null;
const displayObject = k.master as Container;
if (!displayObject) return null;
return (displayObject.getChildByName(RoomEngine.OVERLAY) as NitroSprite) || null;
}
private removeOverlayIconSprite(k: NitroSprite, _arg_2: string): boolean {
if (!k) return false;
let index = k.children.length - 1;
while (index >= 0) {
const child = k.getChildAt(index) as NitroSprite;
if (child) {
if (child.name === _arg_2) {
k.removeChildAt(index);
if (child.children.length) {
const firstChild = child.getChildAt(0) as NitroSprite;
firstChild.parent.removeChild(firstChild);
firstChild.destroy();
}
return true;
}
}
index--;
}
return false;
}
private getOverlayIconSprite(k: NitroSprite, _arg_2: string): NitroSprite {
if (!k) return null;
let index = k.children.length - 1;
while (index >= 0) {
const child = k.getChildAt(index) as NitroSprite;
if (child) {
if (child.name === _arg_2) return child;
}
index--;
}
return null;
}
public getRoomObjects(roomId: number, category: number): IRoomObject[] {
if (this._ready) {
const _local_3 = this.getRoomId(roomId);
const _local_4 = this._roomManager.getRoomInstance(_local_3);
if (_local_4) return _local_4.getRoomObjectsForCategory(category);
}
return [];
}
protected addObjectToTileMap(k: number, _arg_2: IRoomObject): void {
const tileObjectMap = this.getRoomInstanceData(k).tileObjectMap;
if (tileObjectMap) tileObjectMap.addRoomObject(_arg_2);
}
public refreshTileObjectMap(k: number, _arg_2: string): void {
const tileObjectMap = this.getRoomInstanceData(k).tileObjectMap;
if (tileObjectMap) tileObjectMap.populate(this.getRoomObjects(k, RoomObjectCategory.FLOOR));
}
public getRenderRoomMessage(
k: Rectangle,
_arg_2: number,
_arg_3: boolean = false,
_arg_4: boolean = true,
_arg_5: boolean = false,
canvasId: number = -1
): IMessageComposer<unknown[]> {
let canvas: IRoomRenderingCanvas = null;
if (canvasId > -1) {
canvas = this.getRoomInstanceRenderingCanvas(this._activeRoomId, canvasId);
} else {
canvas = this.getActiveRoomInstanceRenderingCanvas();
}
if (!canvas) return null;
if (_arg_5) {
canvas.skipSpriteVisibilityChecking();
}
let _local_8 = -1;
if (!_arg_4 && !(this._roomSessionManager.getSession(this._activeRoomId) == null)) {
_local_8 = this._roomSessionManager.getSession(this._activeRoomId).ownRoomIndex;
}
const _local_9 = new SpriteDataCollector();
const _local_10 = _local_9.getFurniData(k, canvas, this, _local_8);
const _local_11 = _local_9.getRoomRenderingModifiers(this);
const _local_12 = _local_9.getRoomPlanes(k, canvas, this, _arg_2);
if (_arg_5) canvas.resumeSpriteVisibilityChecking();
if (_arg_3) {
//return new RenderRoomThumbnailMessageComposer(_local_12, _local_10, _local_11, this._activeRoomId, this._sessionDataManager._Str_8500);
}
NitroLogger.log(_local_10, _local_11, _local_12);
//return new RenderRoomMessageComposer(_local_12, _local_10, _local_11, this._activeRoomId, this._sessionDataManager._Str_8500);
return null;
}
public createTextureFromRoom(roomId: number, canvasId: number = -1, bounds: Rectangle = null): RenderTexture {
let canvas: IRoomRenderingCanvas = null;
if (canvasId > -1) {
canvas = this.getRoomInstanceRenderingCanvas(this._activeRoomId, canvasId);
} else {
canvas = this.getActiveRoomInstanceRenderingCanvas();
}
let texture: RenderTexture = null;
if (bounds) {
texture = TextureUtils.generateTexture(canvas.master, bounds);
} else {
texture = canvas.getDisplayAsTexture();
}
return texture;
}
public saveTextureAsScreenshot(texture: RenderTexture, saveAsThumbnail: boolean = false): void {
let composer: RenderRoomMessageComposer = null;
if (saveAsThumbnail) composer = new RenderRoomThumbnailMessageComposer();
else composer = new RenderRoomMessageComposer();
composer.assignBitmap(texture);
this._communication.connection.send(composer);
}
public saveBase64AsScreenshot(base64: string, saveAsThumbnail: boolean = false): void {
let composer: RenderRoomMessageComposer = null;
if (saveAsThumbnail) composer = new RenderRoomThumbnailMessageComposer();
else composer = new RenderRoomMessageComposer();
composer.assignBase64(base64);
this._communication.connection.send(composer);
}
public objectsInitialized(k: string): void {
const roomId = this.getRoomIdFromString(k);
this.events.dispatchEvent(new RoomEngineEvent(RoomEngineEvent.OBJECTS_INITIALIZED, roomId));
}
public getRoomId(id: number): string {
return id.toString();
}
private getRoomIdFromString(roomId: string): number {
if (!roomId) return -1;
const split = roomId.split("_");
if (split.length <= 0) return -1;
return parseInt(split[0]) || 0;
}
private getRoomObjectRoomId(object: IRoomObject): string {
if (!object || !object.model) return null;
return object.model.getValue<string>(RoomObjectVariable.OBJECT_ROOM_ID);
}
private getRoomObjectAdUrl(type: string): string {
return this._roomContentLoader.getRoomObjectAdUrl(type);
}
public getPetTypeId(figure: string): number {
let type = -1;
if (figure) {
const parts = figure.split(" ");
if (parts.length > 1) type = parseInt(parts[0]);
}
return type;
}
private getPetType(type: string): string {
if (!type) return null;
const parts = type.split(" ");
if (parts.length > 1) {
const typeId = parseInt(parts[0]);
if (this._roomContentLoader) return this._roomContentLoader.getPetNameForType(typeId);
return "pet";
}
return null;
}
public isRoomContentTypeLoaded(name: string): boolean {
if (!this._roomContentLoader) return false;
return this._roomContentLoader.getCollection(name) !== null;
}
public getPetColorResult(petIndex: number, paletteIndex: number): IPetColorResult {
if (!this._roomContentLoader) return null;
return this._roomContentLoader.getPetColorResult(petIndex, paletteIndex);
}
public getPetColorResultsForTag(petIndex: number, tagName: string): IPetColorResult[] {
if (!this._roomContentLoader) return null;
return this._roomContentLoader.getPetColorResultsForTag(petIndex, tagName);
}
public deleteRoomObject(objectId: number, objectCategory: number): boolean {
if (!this._roomObjectEventHandler || objectCategory !== RoomObjectCategory.WALL) return false;
return this._roomObjectEventHandler.deleteWallItem(this._activeRoomId, objectId);
}
public get connection(): IConnection {
return this._communication.connection;
}
public get sessionDataManager(): ISessionDataManager {
return this._sessionDataManager;
}
public set sessionDataManager(manager: ISessionDataManager) {
this._sessionDataManager = manager;
}
public get roomSessionManager(): IRoomSessionManager {
return this._roomSessionManager;
}
public set roomSessionManager(manager: IRoomSessionManager) {
this._roomSessionManager = manager;
}
public get roomManager(): IRoomManager {
return this._roomManager;
}
public set roomManager(manager: IRoomManager) {
this._roomManager = manager;
}
public get objectEventHandler(): RoomObjectEventHandler {
return this._roomObjectEventHandler;
}
public get roomRendererFactory(): IRoomRendererFactory {
return this._roomRendererFactory;
}
public get visualizationFactory(): IRoomObjectVisualizationFactory {
return this._visualizationFactory;
}
public get logicFactory(): IRoomObjectLogicFactory {
return this._logicFactory;
}
public get activeRoomId(): number {
return this._activeRoomId;
}
public get ready(): boolean {
return this._ready;
}
public get roomContentLoader(): IRoomContentLoader {
return this._roomContentLoader;
}
public get isDecorating(): boolean {
if (!this._roomSessionManager) return false;
const session = this._roomSessionManager.getSession(this._activeRoomId);
return (session && session.isDecorating) || false;
}
private get useOffsetScrolling(): boolean {
return true;
}
public get selectedAvatarId(): number {
if (!this._roomObjectEventHandler) return -1;
return this._roomObjectEventHandler.selectedAvatarId;
}
public getRoomObjectCount(roomId: number, categoryId: number): number {
if (this._roomManager == null) return 0;
return this._roomManager.getRoomInstance(roomId.toString()).getRoomObjectsForCategory(categoryId).length;
}
}