nitro-renderer/packages/room/src/RoomContentLoader.ts

513 lines
16 KiB
TypeScript
Raw Normal View History

2024-03-19 21:53:17 -04:00
import { FurnitureType, IEventDispatcher, IFurnitureData, IGraphicAssetCollection, IPetColorResult, IRoomContentListener, IRoomContentLoader, IRoomObject, RoomObjectCategory, RoomObjectUserType, RoomObjectVariable, RoomObjectVisualizationType } from '@nitrots/api';
import { GetAssetManager } from '@nitrots/assets';
import { GetConfiguration } from '@nitrots/configuration';
import { GetEventDispatcher, RoomContentLoadedEvent } from '@nitrots/events';
import { GetSessionDataManager } from '@nitrots/session';
import { NitroLogger } from '@nitrots/utils';
import { Texture } from 'pixi.js';
2021-05-22 12:16:52 -04:00
import { PetColorResult } from './PetColorResult';
2021-03-16 22:02:09 -04:00
2023-07-18 20:28:28 -04:00
export class RoomContentLoader implements IRoomContentLoader
2021-03-16 22:02:09 -04:00
{
2022-03-02 19:21:30 -05:00
private static PLACE_HOLDER: string = 'place_holder';
private static PLACE_HOLDER_WALL: string = 'place_holder_wall';
private static PLACE_HOLDER_PET: string = 'place_holder_pet';
2021-03-16 22:02:09 -04:00
private static PLACE_HOLDER_DEFAULT: string = RoomContentLoader.PLACE_HOLDER;
2022-03-02 19:21:30 -05:00
private static ROOM: string = 'room';
private static TILE_CURSOR: string = 'tile_cursor';
private static SELECTION_ARROW: string = 'selection_arrow';
2021-03-16 22:02:09 -04:00
2022-07-18 21:51:53 -04:00
public static MANDATORY_LIBRARIES: string[] = [RoomContentLoader.PLACE_HOLDER, RoomContentLoader.PLACE_HOLDER_WALL, RoomContentLoader.PLACE_HOLDER_PET, RoomContentLoader.ROOM, RoomContentLoader.TILE_CURSOR, RoomContentLoader.SELECTION_ARROW];
2021-03-16 22:02:09 -04:00
private _iconListener: IRoomContentListener;
2023-07-18 20:28:28 -04:00
private _images: Map<string, HTMLImageElement> = new Map();
2021-03-16 22:02:09 -04:00
2023-07-18 20:28:28 -04:00
private _activeObjects: { [index: string]: number } = {};
private _activeObjectTypes: Map<number, string> = new Map();
private _activeObjectTypeIds: Map<string, number> = new Map();
private _objectTypeAdUrls: Map<string, string> = new Map();
private _wallItems: { [index: string]: number } = {};
private _wallItemTypes: Map<number, string> = new Map();
private _wallItemTypeIds: Map<string, number> = new Map();
private _furniRevisions: Map<string, number> = new Map();
private _pets: { [index: string]: number } = {};
private _petColors: Map<number, Map<number, IPetColorResult>> = new Map();
private _objectAliases: Map<string, string> = new Map();
private _objectOriginalNames: Map<string, string> = new Map();
2021-03-16 22:02:09 -04:00
2023-07-18 20:28:28 -04:00
private _pendingContentTypes: string[] = [];
2021-03-16 22:02:09 -04:00
2023-07-18 20:28:28 -04:00
public async init(): Promise<void>
2021-03-16 22:02:09 -04:00
{
2024-03-19 21:53:17 -04:00
this.processFurnitureData(GetSessionDataManager().getAllFurnitureData());
2021-03-16 22:02:09 -04:00
2024-03-19 21:53:17 -04:00
for(const [index, name] of GetConfiguration().getValue<string[]>('pet.types').entries()) this._pets[name] = index;
2024-03-26 22:43:29 -04:00
await Promise.all(RoomContentLoader.MANDATORY_LIBRARIES.map(value => this.downloadAsset(value)));
2021-03-16 22:02:09 -04:00
}
2024-03-19 21:53:17 -04:00
public processFurnitureData(furnitureData: IFurnitureData[]): void
2021-03-16 22:02:09 -04:00
{
2022-11-10 11:00:28 -05:00
if(!furnitureData) return;
2021-03-16 22:02:09 -04:00
2022-11-10 11:00:28 -05:00
for(const furniture of furnitureData)
2021-03-16 22:02:09 -04:00
{
2022-11-10 11:00:28 -05:00
if(!furniture) continue;
2021-03-16 22:02:09 -04:00
const id = furniture.id;
let className = furniture.className;
2022-11-10 11:00:28 -05:00
if(furniture.hasIndexedColor) className = ((className + '*') + furniture.colorIndex);
2021-03-16 22:02:09 -04:00
2022-03-02 19:21:30 -05:00
const revision = furniture.revision;
const adUrl = furniture.adUrl;
2021-03-16 22:02:09 -04:00
2022-11-10 11:00:28 -05:00
if(adUrl && adUrl.length > 0) this._objectTypeAdUrls.set(className, adUrl);
2021-03-16 22:02:09 -04:00
let name = furniture.className;
2022-11-10 11:00:28 -05:00
if(furniture.type === FurnitureType.FLOOR)
2021-03-16 22:02:09 -04:00
{
this._activeObjectTypes.set(id, className);
this._activeObjectTypeIds.set(className, id);
2022-11-10 11:00:28 -05:00
if(!this._activeObjects[name]) this._activeObjects[name] = 1;
2021-03-16 22:02:09 -04:00
}
2022-11-10 11:00:28 -05:00
else if(furniture.type === FurnitureType.WALL)
2021-03-16 22:02:09 -04:00
{
2022-11-10 11:00:28 -05:00
if(name === 'post.it')
2021-03-16 22:02:09 -04:00
{
2022-03-02 19:21:30 -05:00
className = 'post_it';
name = 'post_it';
2021-03-16 22:02:09 -04:00
}
2022-11-10 11:00:28 -05:00
if(name === 'post.it.vd')
2021-03-16 22:02:09 -04:00
{
2022-03-02 19:21:30 -05:00
className = 'post_it_vd';
name = 'post_id_vd';
2021-03-16 22:02:09 -04:00
}
this._wallItemTypes.set(id, className);
this._wallItemTypeIds.set(className, id);
2022-11-10 11:00:28 -05:00
if(!this._wallItems[name]) this._wallItems[name] = 1;
2021-03-16 22:02:09 -04:00
}
const existingRevision = this._furniRevisions.get(name);
2022-11-10 11:00:28 -05:00
if(revision > existingRevision)
2021-03-16 22:02:09 -04:00
{
this._furniRevisions.delete(name);
this._furniRevisions.set(name, revision);
}
}
}
public getFurnitureFloorNameForTypeId(typeId: number): string
{
const type = this._activeObjectTypes.get(typeId);
return this.removeColorIndex(type);
}
public getFurnitureWallNameForTypeId(typeId: number, extra: string = null): string
{
let type = this._wallItemTypes.get(typeId);
2022-11-10 11:00:28 -05:00
if((type === 'poster') && (extra !== null)) type = (type + extra);
2021-03-16 22:02:09 -04:00
return this.removeColorIndex(type);
}
public getFurnitureFloorColorIndex(typeId: number): number
{
const type = this._activeObjectTypes.get(typeId);
2022-11-10 11:00:28 -05:00
if(!type) return -1;
2021-03-16 22:02:09 -04:00
return this.getColorIndexFromName(type);
}
public getFurnitureWallColorIndex(typeId: number): number
{
const type = this._wallItemTypes.get(typeId);
2022-11-10 11:00:28 -05:00
if(!type) return -1;
2021-03-16 22:02:09 -04:00
return this.getColorIndexFromName(type);
}
private getColorIndexFromName(name: string): number
{
2022-11-10 11:00:28 -05:00
if(!name) return -1;
2021-03-16 22:02:09 -04:00
const index = name.indexOf('*');
2022-11-10 11:00:28 -05:00
if(index === -1) return 0;
2021-03-16 22:02:09 -04:00
return parseInt(name.substr(index + 1));
}
private removeColorIndex(name: string): string
{
2022-11-10 11:00:28 -05:00
if(!name) return null;
2021-03-16 22:02:09 -04:00
const index = name.indexOf('*');
2022-11-10 11:00:28 -05:00
if(index === -1) return name;
2021-03-16 22:02:09 -04:00
return name.substr(0, index);
}
2021-08-01 00:20:34 -04:00
public getRoomObjectAdUrl(type: string): string
{
const value = this._objectTypeAdUrls.get(type);
2022-11-10 11:00:28 -05:00
if(!value) return '';
2021-08-01 00:20:34 -04:00
return value;
}
2022-11-02 04:25:40 -04:00
public getPetColorResult(petIndex: number, paletteIndex: number): IPetColorResult
2021-05-22 12:16:52 -04:00
{
const colorResults = this._petColors.get(petIndex);
2022-11-10 11:00:28 -05:00
if(!colorResults) return null;
2021-05-22 12:16:52 -04:00
return colorResults.get(paletteIndex);
}
2022-11-02 04:25:40 -04:00
public getPetColorResultsForTag(petIndex: number, tagName: string): IPetColorResult[]
2021-07-10 22:45:05 -04:00
{
2022-03-02 19:21:30 -05:00
const colorResults = this._petColors.get(petIndex);
2022-11-02 04:25:40 -04:00
const results: IPetColorResult[] = [];
2021-07-10 22:45:05 -04:00
2022-11-10 11:00:28 -05:00
if(colorResults)
2021-07-10 22:45:05 -04:00
{
2022-11-10 11:00:28 -05:00
for(const result of colorResults.values())
2021-07-10 22:45:05 -04:00
{
2022-11-10 11:00:28 -05:00
if(result.tag === tagName) results.push(result);
2021-07-10 22:45:05 -04:00
}
}
return results;
}
2021-03-16 22:02:09 -04:00
public getCollection(name: string): IGraphicAssetCollection
{
2024-03-19 21:53:17 -04:00
return GetAssetManager().getCollection(name);
2022-04-10 02:58:33 -04:00
}
2021-03-16 22:02:09 -04:00
public getImage(name: string): HTMLImageElement
{
2022-11-10 11:00:28 -05:00
if(!name) return null;
2021-03-16 22:02:09 -04:00
const existing = this._images.get(name);
2022-11-10 11:00:28 -05:00
if(!existing) return null;
2021-03-16 22:02:09 -04:00
const image = new Image();
image.src = existing.src;
return image;
}
2024-03-19 21:53:17 -04:00
public addAssetToCollection(collectionName: string, assetName: string, texture: Texture, override: boolean = true): boolean
2021-03-16 22:02:09 -04:00
{
2024-03-19 21:53:17 -04:00
return GetAssetManager().addAssetToCollection(collectionName, assetName, texture, override);
2021-03-16 22:02:09 -04:00
}
public getPlaceholderName(type: string): string
{
const category = this.getCategoryForType(type);
2022-11-10 11:00:28 -05:00
switch(category)
2021-03-16 22:02:09 -04:00
{
case RoomObjectCategory.FLOOR:
return RoomContentLoader.PLACE_HOLDER;
case RoomObjectCategory.WALL:
return RoomContentLoader.PLACE_HOLDER_WALL;
default:
2022-11-10 11:00:28 -05:00
if(this._pets[type] !== undefined) return RoomContentLoader.PLACE_HOLDER_PET;
2021-03-16 22:02:09 -04:00
return RoomContentLoader.PLACE_HOLDER_DEFAULT;
}
}
public getCategoryForType(type: string): number
{
2022-11-10 11:00:28 -05:00
if(!type) return RoomObjectCategory.MINIMUM;
2021-03-16 22:02:09 -04:00
2022-11-10 11:00:28 -05:00
if(this._activeObjects[type] !== undefined) return RoomObjectCategory.FLOOR;
2021-03-16 22:02:09 -04:00
2022-11-10 11:00:28 -05:00
if(this._wallItems[type] !== undefined) return RoomObjectCategory.WALL;
2021-03-16 22:02:09 -04:00
2022-11-10 11:00:28 -05:00
if(this._pets[type] !== undefined) return RoomObjectCategory.UNIT;
2021-03-16 22:02:09 -04:00
2022-11-10 11:00:28 -05:00
if(type.indexOf('poster') === 0) return RoomObjectCategory.WALL;
2021-03-16 22:02:09 -04:00
2022-11-10 11:00:28 -05:00
if(type === 'room') return RoomObjectCategory.ROOM;
2021-03-16 22:02:09 -04:00
2022-11-10 11:00:28 -05:00
if(type === RoomObjectUserType.USER) return RoomObjectCategory.UNIT;
2021-03-16 22:02:09 -04:00
2022-11-10 11:00:28 -05:00
if(type === RoomObjectUserType.PET) return RoomObjectCategory.UNIT;
2021-03-16 22:02:09 -04:00
2022-11-10 11:00:28 -05:00
if(type === RoomObjectUserType.BOT) return RoomObjectCategory.UNIT;
2021-03-16 22:02:09 -04:00
2022-11-10 11:00:28 -05:00
if(type === RoomObjectUserType.RENTABLE_BOT) return RoomObjectCategory.UNIT;
2021-03-16 22:02:09 -04:00
2022-11-10 11:00:28 -05:00
if((type === RoomContentLoader.TILE_CURSOR) || (type === RoomContentLoader.SELECTION_ARROW)) return RoomObjectCategory.CURSOR;
2021-03-16 22:02:09 -04:00
return RoomObjectCategory.MINIMUM;
}
public getPetNameForType(type: number): string
{
2024-03-19 21:53:17 -04:00
return GetConfiguration().getValue<string[]>('pet.types')[type] || null;
2021-03-16 22:02:09 -04:00
}
public isLoaderType(type: string): boolean
{
type = RoomObjectUserType.getRealType(type);
2022-11-10 11:00:28 -05:00
if(type === RoomObjectVisualizationType.USER) return false;
2021-03-16 22:02:09 -04:00
return true;
}
public downloadImage(id: number, type: string, param: string, events: IEventDispatcher = null): boolean
{
2022-03-02 19:21:30 -05:00
let typeName: string = null;
2021-03-16 22:02:09 -04:00
let assetUrls: string[] = [];
2022-11-10 11:00:28 -05:00
if(type && (type.indexOf(',') >= 0))
2021-03-16 22:02:09 -04:00
{
2022-03-02 19:21:30 -05:00
typeName = type;
type = typeName.split(',')[0];
2021-03-16 22:02:09 -04:00
}
2022-11-10 11:00:28 -05:00
if(typeName)
2021-03-16 22:02:09 -04:00
{
assetUrls = this.getAssetUrls(typeName, param, true);
}
else
{
assetUrls = this.getAssetUrls(type, param, true);
}
2022-11-10 11:00:28 -05:00
if(assetUrls && assetUrls.length)
2021-03-16 22:02:09 -04:00
{
const url = assetUrls[0];
const image = new Image();
image.src = url;
image.onload = () =>
{
image.onerror = null;
2022-07-18 21:51:53 -04:00
this._images.set(([type, param].join('_')), image);
2021-03-16 22:02:09 -04:00
2022-07-18 21:51:53 -04:00
this._iconListener.onRoomContentLoaded(id, [type, param].join('_'), true);
2021-03-16 22:02:09 -04:00
};
image.onerror = () =>
{
image.onload = null;
2022-11-08 16:44:41 -05:00
NitroLogger.error('Failed to download asset', url);
2021-03-16 22:02:09 -04:00
2022-07-18 21:51:53 -04:00
this._iconListener.onRoomContentLoaded(id, [type, param].join('_'), false);
2021-03-16 22:02:09 -04:00
};
return true;
}
return false;
}
2023-07-18 20:28:28 -04:00
public async downloadAsset(type: string): Promise<void>
2021-03-16 22:02:09 -04:00
{
2022-11-14 00:22:26 -05:00
const assetUrl: string = this.getAssetUrls(type)?.[0];
2021-03-16 22:02:09 -04:00
2022-11-14 00:22:26 -05:00
if(!assetUrl || !assetUrl.length) return;
2021-03-16 22:02:09 -04:00
2023-07-18 20:28:28 -04:00
if((this._pendingContentTypes.indexOf(type) >= 0)) return;
2021-03-16 22:02:09 -04:00
this._pendingContentTypes.push(type);
2024-03-19 21:53:17 -04:00
if(!await GetAssetManager().downloadAsset(assetUrl))
2021-03-16 22:02:09 -04:00
{
2024-03-19 21:53:17 -04:00
GetEventDispatcher().dispatchEvent(new RoomContentLoadedEvent(RoomContentLoadedEvent.RCLE_FAILURE, type));
2024-03-19 21:53:17 -04:00
return;
}
2021-03-16 22:02:09 -04:00
2024-03-19 21:53:17 -04:00
const petIndex = this._pets[type];
2021-03-16 22:02:09 -04:00
2024-03-19 21:53:17 -04:00
if(petIndex !== undefined)
{
const collection = this.getCollection(type);
const keys = collection.getPaletteNames();
const palettes: Map<number, IPetColorResult> = new Map();
2021-03-16 22:02:09 -04:00
2024-03-19 21:53:17 -04:00
for(const key of keys)
2023-07-18 20:28:28 -04:00
{
2024-03-19 21:53:17 -04:00
const palette = collection.getPalette(key);
const paletteData = collection.data.palettes[key];
2022-04-10 02:58:33 -04:00
2024-03-19 21:53:17 -04:00
const primaryColor = palette.primaryColor;
const secondaryColor = palette.secondaryColor;
const breed = ((paletteData.breed !== undefined) ? paletteData.breed : 0);
const tag = ((paletteData.colorTag !== undefined) ? paletteData.colorTag : -1);
const master = ((paletteData.master !== undefined) ? paletteData.master : false);
const layerTags = ((paletteData.tags !== undefined) ? paletteData.tags : []);
2022-04-10 02:58:33 -04:00
2024-03-19 21:53:17 -04:00
palettes.set(parseInt(key), new PetColorResult(primaryColor, secondaryColor, breed, tag, key, master, layerTags));
2021-03-16 22:02:09 -04:00
}
2023-07-18 20:28:28 -04:00
2024-03-19 21:53:17 -04:00
this._petColors.set(petIndex, palettes);
2022-11-14 00:22:26 -05:00
}
2021-03-16 22:02:09 -04:00
2024-03-19 21:53:17 -04:00
GetEventDispatcher().dispatchEvent(new RoomContentLoadedEvent(RoomContentLoadedEvent.RCLE_SUCCESS, type));
2022-04-10 02:58:33 -04:00
}
2021-03-16 22:02:09 -04:00
2024-03-19 21:53:17 -04:00
public getAssetAliasName(name: string): string
2022-04-10 02:58:33 -04:00
{
2024-03-19 21:53:17 -04:00
const existing = this._objectAliases.get(name);
2021-03-16 22:02:09 -04:00
2024-03-19 21:53:17 -04:00
if(!existing) return name;
2022-11-14 00:22:26 -05:00
2024-03-19 21:53:17 -04:00
return existing;
2021-03-16 22:02:09 -04:00
}
public setAssetAliasName(name: string, originalName: string): void
{
this._objectAliases.set(name, originalName);
this._objectOriginalNames.set(originalName, name);
}
private getAssetOriginalName(name: string): string
{
const existing = this._objectOriginalNames.get(name);
2022-11-10 11:00:28 -05:00
if(!existing) return name;
2021-03-16 22:02:09 -04:00
return existing;
}
public getAssetUrls(type: string, param: string = null, icon: boolean = false): string[]
{
2022-11-10 11:00:28 -05:00
switch(type)
2021-03-16 22:02:09 -04:00
{
case RoomContentLoader.PLACE_HOLDER:
2022-07-18 21:51:53 -04:00
return [this.getAssetUrlWithGenericBase(RoomContentLoader.PLACE_HOLDER)];
2021-03-16 22:02:09 -04:00
case RoomContentLoader.PLACE_HOLDER_WALL:
2022-07-18 21:51:53 -04:00
return [this.getAssetUrlWithGenericBase(RoomContentLoader.PLACE_HOLDER_WALL)];
2021-03-16 22:02:09 -04:00
case RoomContentLoader.PLACE_HOLDER_PET:
2022-07-18 21:51:53 -04:00
return [this.getAssetUrlWithGenericBase(RoomContentLoader.PLACE_HOLDER_PET)];
2021-03-16 22:02:09 -04:00
case RoomContentLoader.ROOM:
2022-07-18 21:51:53 -04:00
return [this.getAssetUrlWithGenericBase('room')];
2021-03-16 22:02:09 -04:00
case RoomContentLoader.TILE_CURSOR:
2022-07-18 21:51:53 -04:00
return [this.getAssetUrlWithGenericBase(RoomContentLoader.TILE_CURSOR)];
2021-03-16 22:02:09 -04:00
case RoomContentLoader.SELECTION_ARROW:
2022-07-18 21:51:53 -04:00
return [this.getAssetUrlWithGenericBase(RoomContentLoader.SELECTION_ARROW)];
2021-03-16 22:02:09 -04:00
default: {
const category = this.getCategoryForType(type);
2022-11-10 11:00:28 -05:00
if((category === RoomObjectCategory.FLOOR) || (category === RoomObjectCategory.WALL))
2021-03-16 22:02:09 -04:00
{
const name = this.getAssetAliasName(type);
let assetUrl = (icon ? this.getAssetUrlWithFurniIconBase(name) : this.getAssetUrlWithFurniBase(type));
2022-11-10 11:00:28 -05:00
if(icon)
2021-03-16 22:02:09 -04:00
{
const active = (param && (param !== '') && (this._activeObjectTypeIds.has((name + '*' + param))));
assetUrl = (assetUrl.replace(/%param%/gi, (active ? ('_' + param) : '')));
}
2022-07-18 21:51:53 -04:00
return [assetUrl];
2021-03-16 22:02:09 -04:00
}
2022-11-10 11:00:28 -05:00
if(category === RoomObjectCategory.UNIT)
2021-03-16 22:02:09 -04:00
{
2022-07-18 21:51:53 -04:00
return [this.getAssetUrlWithPetBase(type)];
2021-03-16 22:02:09 -04:00
}
return null;
}
}
}
public getAssetIconUrl(type: string, colorIndex: string): string
{
2022-03-02 19:21:30 -05:00
let assetName: string = null;
2021-03-16 22:02:09 -04:00
let assetUrls: string[] = [];
2022-11-10 11:00:28 -05:00
if(type && (type.indexOf(',') >= 0))
2021-03-16 22:02:09 -04:00
{
assetName = type;
type = assetName.split(',')[0];
}
2022-11-10 11:00:28 -05:00
if(assetName)
2021-03-16 22:02:09 -04:00
{
assetUrls = this.getAssetUrls(assetName, colorIndex, true);
}
else
{
assetUrls = this.getAssetUrls(type, colorIndex, true);
}
2022-11-10 11:00:28 -05:00
if(assetUrls && assetUrls.length) return assetUrls[0];
2021-03-16 22:02:09 -04:00
return null;
}
2021-08-19 03:33:05 -04:00
private getAssetUrlWithGenericBase(assetName: string): string
2021-03-16 22:02:09 -04:00
{
2024-03-19 21:53:17 -04:00
return (GetConfiguration().getValue<string>('generic.asset.url').replace(/%libname%/gi, assetName));
2021-03-16 22:02:09 -04:00
}
public getAssetUrlWithFurniBase(assetName: string): string
{
2024-03-19 21:53:17 -04:00
return (GetConfiguration().getValue<string>('furni.asset.url').replace(/%libname%/gi, assetName));
2021-03-16 22:02:09 -04:00
}
public getAssetUrlWithFurniIconBase(assetName: string): string
{
2024-03-19 21:53:17 -04:00
return (GetConfiguration().getValue<string>('furni.asset.icon.url').replace(/%libname%/gi, assetName));
2021-03-16 22:02:09 -04:00
}
public getAssetUrlWithPetBase(assetName: string): string
{
2024-03-19 21:53:17 -04:00
return (GetConfiguration().getValue<string>('pet.asset.url').replace(/%libname%/gi, assetName));
2021-03-16 22:02:09 -04:00
}
public setRoomObjectRoomId(object: IRoomObject, roomId: string): void
{
const model = object && object.model;
2022-11-10 11:00:28 -05:00
if(!model) return;
2021-03-16 22:02:09 -04:00
model.setValue(RoomObjectVariable.OBJECT_ROOM_ID, roomId);
}
public setIconListener(listener: IRoomContentListener): void
{
this._iconListener = listener;
}
2024-03-19 21:53:17 -04:00
public get pets(): { [index: string]: number }
{
return this._pets;
}
2021-03-16 22:02:09 -04:00
}