From b116ebd02989f1c2148dae3526e66a4e55d8577c Mon Sep 17 00:00:00 2001 From: Bill Date: Wed, 21 Dec 2022 12:31:31 -0500 Subject: [PATCH] Begin HabboRoomContent converter --- src/Main.ts | 4 +- src/common/mapping/json/asset/IAssetData.ts | 5 +- src/common/mapping/json/asset/index.ts | 1 + .../IAssetRoomVisualizationData.ts | 4 + .../json/asset/room-visualization/index.ts | 1 + .../mappers/asset/RoomVisualizationMapper.ts | 20 ++++ src/common/mapping/mappers/asset/index.ts | 1 + src/common/mapping/xml/asset/index.ts | 1 + .../PlaneAnimationLayerItemXML.ts | 68 +++++++++++++ .../PlaneAnimationLayerXML.ts | 23 +++++ .../asset/room-visualization/PlaneLayerXML.ts | 40 ++++++++ .../PlaneMaterialCellColumnXML.ts | 41 ++++++++ .../PlaneMaterialCellExtraItemDataXML.ts | 80 +++++++++++++++ .../PlaneMaterialCellMatrixXML.ts | 69 +++++++++++++ .../PlaneMaterialCellXML.ts | 29 ++++++ .../room-visualization/PlaneMaterialXML.ts | 34 +++++++ .../PlaneTextureBitmapXML.ts | 47 +++++++++ .../room-visualization/PlaneTextureXML.ts | 34 +++++++ .../PlaneVisualizationDataXML.ts | 80 +++++++++++++++ .../PlaneVisualizationXML.ts | 47 +++++++++ .../xml/asset/room-visualization/PlaneXML.ts | 62 ++++++++++++ .../RoomVisualizationXML.ts | 43 ++++++++ .../xml/asset/room-visualization/index.ts | 1 + .../asset/visualization/VisualizationXML.ts | 10 +- src/swf/SWFUtilities.ts | 98 ++++++++++++------- 25 files changed, 801 insertions(+), 42 deletions(-) create mode 100644 src/common/mapping/json/asset/room-visualization/IAssetRoomVisualizationData.ts create mode 100644 src/common/mapping/json/asset/room-visualization/index.ts create mode 100644 src/common/mapping/mappers/asset/RoomVisualizationMapper.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/PlaneAnimationLayerItemXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/PlaneAnimationLayerXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/PlaneLayerXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellColumnXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellExtraItemDataXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellMatrixXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/PlaneMaterialXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/PlaneTextureBitmapXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/PlaneTextureXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/PlaneVisualizationDataXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/PlaneVisualizationXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/PlaneXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/RoomVisualizationXML.ts create mode 100644 src/common/mapping/xml/asset/room-visualization/index.ts diff --git a/src/Main.ts b/src/Main.ts index 2d10ea9..c7ff776 100644 --- a/src/Main.ts +++ b/src/Main.ts @@ -32,12 +32,14 @@ import { ProductDataConverter } from './converters/ProductDataConverter'; const bundle = (process.argv.indexOf('--bundle') >= 0); const extract = (process.argv.indexOf('--extract') >= 0); const convertSwf = (process.argv.indexOf('--convert-swf') >= 0); - const skip = (bundle || extract || convertSwf); + const skip = (bundle || extract || convertSwf || true); if (skip) { const extractor = container.resolve(ConverterUtilities); + await extractor.convertSwfFromFolder(); + bundle && await extractor.bundleExtractedFromFolder(); extract && await extractor.extractNitroFromFolder(); convertSwf && await extractor.convertSwfFromFolder(); diff --git a/src/common/mapping/json/asset/IAssetData.ts b/src/common/mapping/json/asset/IAssetData.ts index 884ee67..835ca6a 100644 --- a/src/common/mapping/json/asset/IAssetData.ts +++ b/src/common/mapping/json/asset/IAssetData.ts @@ -3,10 +3,12 @@ import { IAsset } from './IAsset'; import { IAssetAlias } from './IAssetAlias'; import { IAssetPalette } from './IAssetPalette'; import { IAssetLogicData } from './logic/IAssetLogicData'; +import { IAssetRoomVisualizationData } from './room-visualization'; import { ISpritesheetData } from './spritesheet'; import { IAssetVisualizationData } from './visualization'; -export interface IAssetData { +export interface IAssetData +{ type?: string; name?: string; visualizationType?: string; @@ -18,4 +20,5 @@ export interface IAssetData { animations?: { [index: string]: IAssetAnimation }; palettes?: { [index: string]: IAssetPalette }; visualizations?: IAssetVisualizationData[]; + roomVisualization?: IAssetRoomVisualizationData; } diff --git a/src/common/mapping/json/asset/index.ts b/src/common/mapping/json/asset/index.ts index 3d5fabb..3893764 100644 --- a/src/common/mapping/json/asset/index.ts +++ b/src/common/mapping/json/asset/index.ts @@ -4,5 +4,6 @@ export * from './IAssetAlias'; export * from './IAssetData'; export * from './IAssetPalette'; export * from './logic'; +export * from './room-visualization'; export * from './spritesheet'; export * from './visualization'; diff --git a/src/common/mapping/json/asset/room-visualization/IAssetRoomVisualizationData.ts b/src/common/mapping/json/asset/room-visualization/IAssetRoomVisualizationData.ts new file mode 100644 index 0000000..e91ce24 --- /dev/null +++ b/src/common/mapping/json/asset/room-visualization/IAssetRoomVisualizationData.ts @@ -0,0 +1,4 @@ +export interface IAssetRoomVisualizationData +{ + +} diff --git a/src/common/mapping/json/asset/room-visualization/index.ts b/src/common/mapping/json/asset/room-visualization/index.ts new file mode 100644 index 0000000..23bfca7 --- /dev/null +++ b/src/common/mapping/json/asset/room-visualization/index.ts @@ -0,0 +1 @@ +export * from './IAssetRoomVisualizationData'; diff --git a/src/common/mapping/mappers/asset/RoomVisualizationMapper.ts b/src/common/mapping/mappers/asset/RoomVisualizationMapper.ts new file mode 100644 index 0000000..68c4dea --- /dev/null +++ b/src/common/mapping/mappers/asset/RoomVisualizationMapper.ts @@ -0,0 +1,20 @@ +import { IAssetData } from '../../json'; +import { RoomVisualizationXML } from '../../xml'; +import { Mapper } from './Mapper'; + +export class RoomVisualizationMapper extends Mapper +{ + public static mapXML(visualization: any, output: IAssetData): void + { + if (!visualization || !output) return; + + RoomVisualizationMapper.mapVisualizationXML(new RoomVisualizationXML(visualization.visualizationData), output); + } + + private static mapVisualizationXML(xml: RoomVisualizationXML, output: IAssetData): void + { + if (!xml || !output) return; + + console.log(xml); + } +} diff --git a/src/common/mapping/mappers/asset/index.ts b/src/common/mapping/mappers/asset/index.ts index 8303c33..f34701f 100644 --- a/src/common/mapping/mappers/asset/index.ts +++ b/src/common/mapping/mappers/asset/index.ts @@ -4,4 +4,5 @@ export * from './IndexMapper'; export * from './LogicMapper'; export * from './ManifestMapper'; export * from './Mapper'; +export * from './RoomVisualizationMapper'; export * from './VisualizationMapper'; diff --git a/src/common/mapping/xml/asset/index.ts b/src/common/mapping/xml/asset/index.ts index 0a600b7..849567a 100644 --- a/src/common/mapping/xml/asset/index.ts +++ b/src/common/mapping/xml/asset/index.ts @@ -4,4 +4,5 @@ export * from './index'; export * from './IndexXML'; export * from './logic'; export * from './manifest'; +export * from './room-visualization'; export * from './visualization'; diff --git a/src/common/mapping/xml/asset/room-visualization/PlaneAnimationLayerItemXML.ts b/src/common/mapping/xml/asset/room-visualization/PlaneAnimationLayerItemXML.ts new file mode 100644 index 0000000..3dd4a68 --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/PlaneAnimationLayerItemXML.ts @@ -0,0 +1,68 @@ +export class PlaneAnimationLayerItemXML +{ + private readonly _id: number; + private readonly _assetId: string; + private readonly _x: string; + private readonly _y: string; + private readonly _randomX: string; + private readonly _randomY: string; + private readonly _speedX: number; + private readonly _speedY: number; + + constructor(xml: any) + { + const attributes = xml.$; + + if (attributes !== undefined) + { + if (attributes.id !== undefined) this._id = parseInt(attributes.id); + if (attributes.assetId !== undefined) this._assetId = attributes.assetId; + if (attributes.x !== undefined) this._x = attributes.x; + if (attributes.y !== undefined) this._y = attributes.y; + if (attributes.randomX !== undefined) this._randomX = attributes.randomX; + if (attributes.randomY !== undefined) this._randomY = attributes.randomY; + if (attributes.speedX !== undefined) this._speedX = parseFloat(attributes.speedX); + if (attributes.speedY !== undefined) this._speedY = parseFloat(attributes.speedY); + } + } + + public get id(): number + { + return this._id; + } + + public get assetId(): string + { + return this._assetId; + } + + public get x(): string + { + return this._x; + } + + public get y(): string + { + return this._y; + } + + public get randomX(): string + { + return this._randomX; + } + + public get randomY(): string + { + return this._randomY; + } + + public get speedX(): number + { + return this._speedX; + } + + public get speedY(): number + { + return this._speedY; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/PlaneAnimationLayerXML.ts b/src/common/mapping/xml/asset/room-visualization/PlaneAnimationLayerXML.ts new file mode 100644 index 0000000..e4ced67 --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/PlaneAnimationLayerXML.ts @@ -0,0 +1,23 @@ +import { PlaneAnimationLayerItemXML } from './PlaneAnimationLayerItemXML'; + +export class PlaneAnimationLayerXML +{ + private readonly _items: PlaneAnimationLayerItemXML[]; + + constructor(xml: any) + { + const attributes = xml.$; + + if ((xml.animationItem !== undefined) && Array.isArray(xml.animationItem)) + { + this._items = []; + + for (const item of xml.animationItem) this._items.push(new PlaneAnimationLayerItemXML(item)); + } + } + + public get items(): PlaneAnimationLayerItemXML[] + { + return this._items; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/PlaneLayerXML.ts b/src/common/mapping/xml/asset/room-visualization/PlaneLayerXML.ts new file mode 100644 index 0000000..bcc07a8 --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/PlaneLayerXML.ts @@ -0,0 +1,40 @@ +export class PlaneLayerXML +{ + private readonly _materialId: string; + private readonly _color: number; + private readonly _offset: number; + private readonly _align: string; + + constructor(xml: any) + { + const attributes = xml.$; + + if (attributes !== undefined) + { + if (attributes.materialId !== undefined) this._materialId = attributes.materialId; + if (attributes.color !== undefined) this._color = parseInt(attributes.color, 16); + if (attributes.offset !== undefined) this._offset = parseInt(attributes.offset); + if (attributes.align !== undefined) this._align = attributes.align; + } + } + + public get materialId(): string + { + return this._materialId; + } + + public get color(): number + { + return this._color; + } + + public get offset(): number + { + return this._offset; + } + + public get align(): string + { + return this._align; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellColumnXML.ts b/src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellColumnXML.ts new file mode 100644 index 0000000..8255b7f --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellColumnXML.ts @@ -0,0 +1,41 @@ +import { PlaneMaterialCellXML } from './PlaneMaterialCellXML'; + +export class PlaneMaterialCellColumnXML +{ + private readonly _repeatMode: string; + private readonly _width: number; + private readonly _cells: PlaneMaterialCellXML[]; + + constructor(xml: any) + { + const attributes = xml.$; + + if (attributes !== undefined) + { + if (attributes.repeatMode !== undefined) this._repeatMode = attributes.repeatMode; + if (attributes.width !== undefined) this._width = parseInt(attributes.width); + } + + if ((xml.materialCell !== undefined) && Array.isArray(xml.materialCell)) + { + this._cells = []; + + for (const cell of xml.materialCell) this._cells.push(new PlaneMaterialCellXML(cell)); + } + } + + public get repeatMode(): string + { + return this._repeatMode; + } + + public get width(): number + { + return this._width; + } + + public get cells(): PlaneMaterialCellXML[] + { + return this._cells; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellExtraItemDataXML.ts b/src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellExtraItemDataXML.ts new file mode 100644 index 0000000..2dc1f49 --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellExtraItemDataXML.ts @@ -0,0 +1,80 @@ + +export class PlaneMaterialCellExtraItemDataXML +{ + private readonly _limitMax: number; + private readonly _extraItemTypes: string[]; + private readonly _offsets: [number, number][]; + + constructor(xml: any) + { + const attributes = xml.$; + + if (attributes !== undefined) + { + if (attributes.limitMax !== undefined) this._limitMax = parseInt(attributes.limitMax); + } + + if ((xml.extraItemTypes !== undefined) && Array.isArray(xml.extraItemTypes)) + { + this._extraItemTypes = []; + + for (const item of xml.extraItemTypes) + { + if (item.extraItemType && Array.isArray(item.extraItemType)) + { + for (const itemType of item.extraItemType) + { + const attributes = itemType.$; + + if (attributes !== undefined) + { + if (attributes.assetName !== undefined) this._extraItemTypes.push(attributes.assetName); + } + } + } + } + } + + if ((xml.offsets !== undefined) && Array.isArray(xml.offsets)) + { + this._offsets = []; + + for (const offset of xml.offsets) + { + if (offset.offset && Array.isArray(offset.offset)) + { + for (const child of offset.offset) + { + const attributes = child.$; + + let x = 0; + let y = 0; + + if (attributes !== undefined) + { + if (attributes.x !== undefined) x = parseInt(attributes.x); + if (attributes.y !== undefined) y = parseInt(attributes.y); + } + + this._offsets.push([x, y]); + } + } + } + } + } + + public get limitMax(): number + { + return this._limitMax; + } + + public get extraItemTypes(): string[] + { + return this._extraItemTypes; + } + + public get offsets(): [number, number][] + { + return this._offsets; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellMatrixXML.ts b/src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellMatrixXML.ts new file mode 100644 index 0000000..80af11b --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellMatrixXML.ts @@ -0,0 +1,69 @@ +import { PlaneMaterialCellColumnXML } from './PlaneMaterialCellColumnXML'; + +export class PlaneMaterialCellMatrixXML +{ + private readonly _repeatMode: string; + private readonly _align: string; + private readonly _normalMinX: number; + private readonly _normalMaxX: number; + private readonly _normalMinY: number; + private readonly _normalMaxY: number; + private readonly _columns: PlaneMaterialCellColumnXML[]; + + constructor(xml: any) + { + const attributes = xml.$; + + if (attributes !== undefined) + { + if (attributes.repeatMode !== undefined) this._repeatMode = attributes.repeatMode; + if (attributes.align !== undefined) this._align = attributes.align; + if (attributes.normalMinX !== undefined) this._normalMinX = parseFloat(attributes.normalMinX); + if (attributes.normalMaxX !== undefined) this._normalMaxX = parseFloat(attributes.normalMaxX); + if (attributes.normalMinY !== undefined) this._normalMinY = parseFloat(attributes.normalMinY); + if (attributes.normalMaxY !== undefined) this._normalMaxY = parseFloat(attributes.normalMaxY); + } + + if ((xml.materialCellColumn !== undefined) && Array.isArray(xml.materialCellColumn)) + { + this._columns = []; + + for (const column of xml.materialCellColumn) this._columns.push(new PlaneMaterialCellColumnXML(column)); + } + } + + public get repeatMode(): string + { + return this._repeatMode; + } + + public get align(): string + { + return this._align; + } + + public get normalMinX(): number + { + return this._normalMinX; + } + + public get normalMaxX(): number + { + return this._normalMaxX; + } + + public get normalMinY(): number + { + return this._normalMinY; + } + + public get normalMaxY(): number + { + return this._normalMaxY; + } + + public get columns(): PlaneMaterialCellColumnXML[] + { + return this._columns; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellXML.ts b/src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellXML.ts new file mode 100644 index 0000000..6705582 --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/PlaneMaterialCellXML.ts @@ -0,0 +1,29 @@ +import { PlaneMaterialCellExtraItemDataXML } from './PlaneMaterialCellExtraItemDataXML'; + +export class PlaneMaterialCellXML +{ + private readonly _textureId: string; + private readonly _extraData: PlaneMaterialCellExtraItemDataXML; + + constructor(xml: any) + { + const attributes = xml.$; + + if (attributes !== undefined) + { + if (attributes.textureId !== undefined) this._textureId = attributes.textureId; + } + + if ((xml.extraItemData !== undefined) && Array.isArray(xml.extraItemData)) this._extraData = new PlaneMaterialCellExtraItemDataXML(xml.extraItemData[0]); + } + + public get textureId(): string + { + return this._textureId; + } + + public get extraData(): PlaneMaterialCellExtraItemDataXML + { + return this._extraData; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/PlaneMaterialXML.ts b/src/common/mapping/xml/asset/room-visualization/PlaneMaterialXML.ts new file mode 100644 index 0000000..a2c0267 --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/PlaneMaterialXML.ts @@ -0,0 +1,34 @@ +import { PlaneMaterialCellMatrixXML } from './PlaneMaterialCellMatrixXML'; + +export class PlaneMaterialXML +{ + private readonly _id: string; + private readonly _matrices: PlaneMaterialCellMatrixXML[]; + + constructor(xml: any) + { + const attributes = xml.$; + + if (attributes !== undefined) + { + if (attributes.id !== undefined) this._id = attributes.id; + } + + if ((xml.materialCellMatrix !== undefined) && Array.isArray(xml.materialCellMatrix)) + { + this._matrices = []; + + for (const matrix of xml.materialCellMatrix) this._matrices.push(new PlaneMaterialCellMatrixXML(matrix)); + } + } + + public get id(): string + { + return this._id; + } + + public get matrices(): PlaneMaterialCellMatrixXML[] + { + return this._matrices; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/PlaneTextureBitmapXML.ts b/src/common/mapping/xml/asset/room-visualization/PlaneTextureBitmapXML.ts new file mode 100644 index 0000000..be0ea28 --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/PlaneTextureBitmapXML.ts @@ -0,0 +1,47 @@ +export class PlaneTextureBitmapXML +{ + private readonly _assetName: string; + private readonly _normalMinX: number; + private readonly _normalMaxX: number; + private readonly _normalMinY: number; + private readonly _normalMaxY: number; + + constructor(xml: any) + { + const attributes = xml.$; + + if (attributes !== undefined) + { + if (attributes.assetName !== undefined) this._assetName = attributes.assetName; + if (attributes.normalMinX !== undefined) this._normalMinX = parseFloat(attributes.normalMinX); + if (attributes.normalMaxX !== undefined) this._normalMaxX = parseFloat(attributes.normalMaxX); + if (attributes.normalMinY !== undefined) this._normalMinY = parseFloat(attributes.normalMinY); + if (attributes.normalMaxY !== undefined) this._normalMaxY = parseFloat(attributes.normalMaxY); + } + } + + public get assetName(): string + { + return this._assetName; + } + + public get normalMinX(): number + { + return this._normalMinX; + } + + public get normalMaxX(): number + { + return this._normalMaxX; + } + + public get normalMinY(): number + { + return this._normalMinY; + } + + public get normalMaxY(): number + { + return this._normalMaxY; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/PlaneTextureXML.ts b/src/common/mapping/xml/asset/room-visualization/PlaneTextureXML.ts new file mode 100644 index 0000000..898cd37 --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/PlaneTextureXML.ts @@ -0,0 +1,34 @@ +import { PlaneTextureBitmapXML } from './PlaneTextureBitmapXML'; + +export class PlaneTextureXML +{ + private readonly _id: string; + private readonly _bitmaps: PlaneTextureBitmapXML[]; + + constructor(xml: any) + { + const attributes = xml.$; + + if (attributes !== undefined) + { + if (attributes.id !== undefined) this._id = attributes.id; + } + + if ((xml.bitmap !== undefined) && Array.isArray(xml.bitmap)) + { + this._bitmaps = []; + + for (const bitmap of xml.bitmap) this._bitmaps.push(new PlaneTextureBitmapXML(bitmap)); + } + } + + public get id(): string + { + return this._id; + } + + public get bitmaps(): PlaneTextureBitmapXML[] + { + return this._bitmaps; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/PlaneVisualizationDataXML.ts b/src/common/mapping/xml/asset/room-visualization/PlaneVisualizationDataXML.ts new file mode 100644 index 0000000..78542a4 --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/PlaneVisualizationDataXML.ts @@ -0,0 +1,80 @@ +import { PlaneMaterialXML } from './PlaneMaterialXML'; +import { PlaneTextureXML } from './PlaneTextureXML'; +import { PlaneVisualizationXML } from './PlaneVisualizationXML'; + +export class PlaneVisualizationDataXML +{ + private readonly _planes: PlaneVisualizationXML[]; + private readonly _materials: PlaneMaterialXML[]; + private readonly _textures: PlaneTextureXML[]; + + constructor(xml: any) + { + const attributes = xml.$; + + if ((xml.walls !== undefined) && Array.isArray(xml.walls)) + { + this._planes = []; + + for (const wallParent of xml.walls) + { + if (Array.isArray(wallParent.wall)) for (const wall of wallParent.wall) this._planes.push(new PlaneVisualizationXML(wall)); + } + } + + else if ((xml.floors !== undefined) && Array.isArray(xml.floors)) + { + this._planes = []; + + for (const floorParent of xml.floors) + { + if (Array.isArray(floorParent.floor)) for (const floor of floorParent.floor) this._planes.push(new PlaneVisualizationXML(floor)); + } + } + + else if ((xml.landscapes !== undefined) && Array.isArray(xml.landscapes)) + { + this._planes = []; + + for (const landscapeParent of xml.landscapes) + { + if (Array.isArray(landscapeParent.landscape)) for (const landscape of landscapeParent.landscape) this._planes.push(new PlaneVisualizationXML(landscape)); + } + } + + if ((xml.materials !== undefined) && Array.isArray(xml.materials)) + { + this._materials = []; + + for (const materialParent of xml.materials) + { + if (Array.isArray(materialParent.material)) for (const material of materialParent.material) this._materials.push(new PlaneMaterialXML(material)); + } + } + + if ((xml.textures !== undefined) && Array.isArray(xml.textures)) + { + this._textures = []; + + for (const textureParent of xml.textures) + { + if (Array.isArray(textureParent.texture)) for (const texture of textureParent.texture) this._textures.push(new PlaneTextureXML(texture)); + } + } + } + + public get planes(): PlaneVisualizationXML[] + { + return this._planes; + } + + public get materials(): PlaneMaterialXML[] + { + return this._materials; + } + + public get textures(): PlaneTextureXML[] + { + return this._textures; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/PlaneVisualizationXML.ts b/src/common/mapping/xml/asset/room-visualization/PlaneVisualizationXML.ts new file mode 100644 index 0000000..c916ea0 --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/PlaneVisualizationXML.ts @@ -0,0 +1,47 @@ +import { PlaneXML } from './PlaneXML'; + +export class PlaneVisualizationXML +{ + private readonly _id: string; + private readonly _visualizations: PlaneXML[]; + private readonly _animatedVisualization: PlaneXML[]; + + constructor(xml: any) + { + const attributes = xml.$; + + if (attributes !== undefined) + { + if (attributes.id !== undefined) this._id = attributes.id; + } + + if ((xml.visualization !== undefined) && Array.isArray(xml.visualization)) + { + this._visualizations = []; + + for (const visualization of xml.visualization) this._visualizations.push(new PlaneXML(visualization)); + } + + if ((xml.animatedVisualization !== undefined) && Array.isArray(xml.animatedVisualization)) + { + this._animatedVisualization = []; + + for (const visualization of xml.animatedVisualization) this._animatedVisualization.push(new PlaneXML(visualization)); + } + } + + public get id(): string + { + return this._id; + } + + public get visualizations(): PlaneXML[] + { + return this._visualizations; + } + + public get animatedVisualization(): PlaneXML[] + { + return this._animatedVisualization; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/PlaneXML.ts b/src/common/mapping/xml/asset/room-visualization/PlaneXML.ts new file mode 100644 index 0000000..50eb124 --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/PlaneXML.ts @@ -0,0 +1,62 @@ +import { PlaneAnimationLayerXML } from './PlaneAnimationLayerXML'; +import { PlaneLayerXML } from './PlaneLayerXML'; + +export class PlaneXML +{ + private readonly _size: number; + private readonly _horizontalAngle: number; + private readonly _verticalAngle: number; + private readonly _layers: PlaneLayerXML[]; + private readonly _animatedLayers: PlaneAnimationLayerXML[]; + + constructor(xml: any) + { + const attributes = xml.$; + + if (attributes !== undefined) + { + if (attributes.size !== undefined) this._size = parseInt(attributes.size); + if (attributes.horizontalAngle !== undefined) this._horizontalAngle = parseFloat(attributes.horizontalAngle); + if (attributes.verticalAngle !== undefined) this._verticalAngle = parseFloat(attributes.verticalAngle); + } + + if ((xml.visualizationLayer !== undefined) && Array.isArray(xml.visualizationLayer)) + { + this._layers = []; + + for (const layer of xml.visualizationLayer) this._layers.push(new PlaneLayerXML(layer)); + } + + if ((xml.animationLayer !== undefined) && Array.isArray(xml.animationLayer)) + { + this._animatedLayers = []; + + for (const layer of xml.animationLayer) this._animatedLayers.push(new PlaneAnimationLayerXML(layer)); + } + } + + public get size(): number + { + return this._size; + } + + public get horizontalAngle(): number + { + return this._horizontalAngle; + } + + public get verticalAngle(): number + { + return this._verticalAngle; + } + + public get layers(): PlaneLayerXML[] + { + return this._layers; + } + + public get animatedLayers(): PlaneAnimationLayerXML[] + { + return this._animatedLayers; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/RoomVisualizationXML.ts b/src/common/mapping/xml/asset/room-visualization/RoomVisualizationXML.ts new file mode 100644 index 0000000..00e091d --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/RoomVisualizationXML.ts @@ -0,0 +1,43 @@ +import { PlaneVisualizationDataXML } from './PlaneVisualizationDataXML'; + +export class RoomVisualizationXML +{ + private readonly _wallData: PlaneVisualizationDataXML; + private readonly _floorData: PlaneVisualizationDataXML; + private readonly _landscapeData: PlaneVisualizationDataXML; + + constructor(xml: any) + { + const attributes = xml.$; + + if ((xml.wallData !== undefined) && Array.isArray(xml.wallData)) + { + this._wallData = new PlaneVisualizationDataXML(xml.wallData[0]); + } + + if ((xml.floorData !== undefined) && Array.isArray(xml.floorData)) + { + this._floorData = new PlaneVisualizationDataXML(xml.floorData[0]); + } + + if ((xml.landscapeData !== undefined) && Array.isArray(xml.landscapeData)) + { + this._landscapeData = new PlaneVisualizationDataXML(xml.landscapeData[0]); + } + } + + public get wallData(): PlaneVisualizationDataXML + { + return this._wallData; + } + + public get floorData(): PlaneVisualizationDataXML + { + return this._floorData; + } + + public get landscapeData(): PlaneVisualizationDataXML + { + return this._landscapeData; + } +} diff --git a/src/common/mapping/xml/asset/room-visualization/index.ts b/src/common/mapping/xml/asset/room-visualization/index.ts new file mode 100644 index 0000000..875c692 --- /dev/null +++ b/src/common/mapping/xml/asset/room-visualization/index.ts @@ -0,0 +1 @@ +export * from './RoomVisualizationXML'; diff --git a/src/common/mapping/xml/asset/visualization/VisualizationXML.ts b/src/common/mapping/xml/asset/visualization/VisualizationXML.ts index 73fc147..8f7f1a6 100644 --- a/src/common/mapping/xml/asset/visualization/VisualizationXML.ts +++ b/src/common/mapping/xml/asset/visualization/VisualizationXML.ts @@ -9,18 +9,18 @@ export class VisualizationXML { const attributes = xml.$; - if(attributes !== undefined) + if (attributes !== undefined) { - if(attributes.type !== undefined) this._type = attributes.type; + if (attributes.type !== undefined) this._type = attributes.type; } - if((xml.graphics !== undefined) && Array.isArray(xml.graphics)) + if ((xml.graphics !== undefined) && Array.isArray(xml.graphics)) { this._visualizations = []; - for(const graphic of xml.graphics) + for (const graphic of xml.graphics) { - if(Array.isArray(graphic.visualization)) for(const visualization of graphic.visualization) this._visualizations.push(new VisualizationDataXML(visualization)); + if (Array.isArray(graphic.visualization)) for (const visualization of graphic.visualization) this._visualizations.push(new VisualizationDataXML(visualization)); } } } diff --git a/src/swf/SWFUtilities.ts b/src/swf/SWFUtilities.ts index e90e72a..1fc208b 100644 --- a/src/swf/SWFUtilities.ts +++ b/src/swf/SWFUtilities.ts @@ -1,6 +1,6 @@ import { wrap } from 'bytebuffer'; import { parseStringPromise } from 'xml2js'; -import { AnimationMapper, AssetMapper, IAssetData, IndexMapper, LogicMapper, ManifestMapper, NitroBundle, SpriteBundle, VisualizationMapper } from '../common'; +import { AnimationMapper, AssetMapper, IAssetData, IndexMapper, LogicMapper, ManifestMapper, NitroBundle, RoomVisualizationMapper, SpriteBundle, VisualizationMapper } from '../common'; import { HabboAssetSWF } from './HabboAssetSWF'; import { DefineBinaryDataTag } from './tags'; @@ -13,26 +13,26 @@ export class SWFUtilities public static createNitroBundle(className: string, assetData: IAssetData, spriteBundle: SpriteBundle): NitroBundle { - if(spriteBundle && (spriteBundle.spritesheet !== undefined)) assetData.spritesheet = spriteBundle.spritesheet; + if (spriteBundle && (spriteBundle.spritesheet !== undefined)) assetData.spritesheet = spriteBundle.spritesheet; const nitroBundle = new NitroBundle(); nitroBundle.addFile((className + '.json'), Buffer.from(JSON.stringify(assetData))); - if(spriteBundle && (spriteBundle.imageData !== undefined)) nitroBundle.addFile(spriteBundle.imageData.name, spriteBundle.imageData.buffer); + if (spriteBundle && (spriteBundle.imageData !== undefined)) nitroBundle.addFile(spriteBundle.imageData.name, spriteBundle.imageData.buffer); return nitroBundle; } public static getBinaryData(habboAssetSWF: HabboAssetSWF, type: string, documentNameTwice: boolean, snakeCase: boolean = false): DefineBinaryDataTag { - let binaryName = habboAssetSWF.getFullClassName(type, documentNameTwice, snakeCase); - let tag = habboAssetSWF.getBinaryTagByName(binaryName); + let binaryName = habboAssetSWF.getFullClassName(type, documentNameTwice, snakeCase); + let tag = habboAssetSWF.getBinaryTagByName(binaryName); - if(!tag) + if (!tag) { - binaryName = habboAssetSWF.getFullClassNameSnake(type, documentNameTwice, true); - tag = habboAssetSWF.getBinaryTagByName(binaryName); + binaryName = habboAssetSWF.getFullClassNameSnake(type, documentNameTwice, true); + tag = habboAssetSWF.getBinaryTagByName(binaryName); } return tag; @@ -42,7 +42,7 @@ export class SWFUtilities { const binaryData = SWFUtilities.getBinaryData(habboAssetSWF, 'manifest', false, snakeCase); - if(!binaryData) return null; + if (!binaryData) return null; return await parseStringPromise(this.removeComments(binaryData.binaryData)); } @@ -51,7 +51,7 @@ export class SWFUtilities { const binaryData = SWFUtilities.getBinaryData(habboAssetSWF, 'index', false, snakeCase); - if(!binaryData) return null; + if (!binaryData) return null; return await parseStringPromise(this.removeComments(binaryData.binaryData)); } @@ -60,7 +60,16 @@ export class SWFUtilities { const binaryData = SWFUtilities.getBinaryData(habboAssetSWF, 'assets', true, snakeCase); - if(!binaryData) return null; + if (!binaryData) return null; + + return await parseStringPromise(this.removeComments(binaryData.binaryData)); + } + + public static async getRoomAssetsXML(habboAssetSWF: HabboAssetSWF, snakeCase: boolean = false): Promise + { + const binaryData = SWFUtilities.getBinaryData(habboAssetSWF, 'room_assets', false, snakeCase); + + if (!binaryData) return null; return await parseStringPromise(this.removeComments(binaryData.binaryData)); } @@ -69,7 +78,7 @@ export class SWFUtilities { const binaryData = SWFUtilities.getBinaryData(habboAssetSWF, 'logic', true, snakeCase); - if(!binaryData) return null; + if (!binaryData) return null; return await parseStringPromise(this.removeComments(binaryData.binaryData)); } @@ -78,7 +87,18 @@ export class SWFUtilities { const binaryData = SWFUtilities.getBinaryData(habboAssetSWF, 'visualization', true, snakeCase); - if(!binaryData) return null; + console.log(binaryData); + + if (!binaryData) return null; + + return await parseStringPromise(this.removeComments(binaryData.binaryData)); + } + + public static async getRoomVisualizationXML(habboAssetSWF: HabboAssetSWF, snakeCase: boolean = false): Promise + { + const binaryData = SWFUtilities.getBinaryData(habboAssetSWF, 'room_visualization', false, snakeCase); + + if (!binaryData) return null; return await parseStringPromise(this.removeComments(binaryData.binaryData)); } @@ -87,37 +107,37 @@ export class SWFUtilities { const binaryData = SWFUtilities.getBinaryData(habboAssetSWF, 'animation', false, snakeCase); - if(!binaryData) return null; + if (!binaryData) return null; return await parseStringPromise(this.removeComments(binaryData.binaryData)); } - public static getPalette(habboAssetSWF: HabboAssetSWF, paletteName: string): [ number, number, number ][] + public static getPalette(habboAssetSWF: HabboAssetSWF, paletteName: string): [number, number, number][] { const binaryData = SWFUtilities.getBinaryData(habboAssetSWF, paletteName, false); - if(!binaryData || !binaryData.binaryDataBuffer) return null; + if (!binaryData || !binaryData.binaryDataBuffer) return null; const byteBuffer = wrap(binaryData.binaryDataBuffer); - const paletteColors: [ number, number, number ][] = []; + const paletteColors: [number, number, number][] = []; let R = 0; let G = 0; let B = 0; let counter = 1; - while((binaryData.binaryDataBuffer.length - byteBuffer.offset) > 0) + while ((binaryData.binaryDataBuffer.length - byteBuffer.offset) > 0) { - if(counter == 1) R = byteBuffer.readUint8(); + if (counter == 1) R = byteBuffer.readUint8(); - else if(counter == 2) G = byteBuffer.readUint8(); + else if (counter == 2) G = byteBuffer.readUint8(); - else if(counter == 3) + else if (counter == 3) { B = byteBuffer.readUint8(); - paletteColors.push([ R, G, B ]); + paletteColors.push([R, G, B]); counter = 0; } @@ -130,61 +150,69 @@ export class SWFUtilities public static async mapXML2JSON(habboAssetSWF: HabboAssetSWF, assetType: string, snakeCase: boolean = false): Promise { - if(!habboAssetSWF) return null; + if (!habboAssetSWF) return null; const output: IAssetData = {}; - if(assetType) output.type = assetType; + if (assetType) output.type = assetType; const indexXML = await this.getIndexXML(habboAssetSWF, snakeCase); - if(indexXML) IndexMapper.mapXML(indexXML, output); + if (indexXML) IndexMapper.mapXML(indexXML, output); const manifestXML = await this.getManifestXML(habboAssetSWF, snakeCase); - if(manifestXML) ManifestMapper.mapXML(manifestXML, output); + if (manifestXML) ManifestMapper.mapXML(manifestXML, output); const assetXML = await this.getAssetsXML(habboAssetSWF, snakeCase); - if(assetXML) + if (assetXML) { AssetMapper.mapXML(assetXML, output); - if(output.palettes !== undefined) + if (output.palettes !== undefined) { - for(const paletteId in output.palettes) + for (const paletteId in output.palettes) { const palette = output.palettes[paletteId]; const paletteColors = this.getPalette(habboAssetSWF, palette.source); - if(!paletteColors) + if (!paletteColors) { delete output.palettes[paletteId]; continue; } - const rgbs: [ number, number, number ][] = []; + const rgbs: [number, number, number][] = []; - for(const rgb of paletteColors) rgbs.push([ rgb[0], rgb[1], rgb[2] ]); + for (const rgb of paletteColors) rgbs.push([rgb[0], rgb[1], rgb[2]]); palette.rgb = rgbs; } } } + const roomAssetXML = await this.getRoomAssetsXML(habboAssetSWF, snakeCase); + + if (assetXML) AssetMapper.mapXML(roomAssetXML, output); + const animationXML = await this.getAnimationXML(habboAssetSWF, snakeCase); - if(animationXML) AnimationMapper.mapXML(animationXML, output); + if (animationXML) AnimationMapper.mapXML(animationXML, output); const logicXML = await this.getLogicXML(habboAssetSWF, snakeCase); - if(logicXML) LogicMapper.mapXML(logicXML, output); + if (logicXML) LogicMapper.mapXML(logicXML, output); const visualizationXML = await this.getVisualizationXML(habboAssetSWF, snakeCase); - if(visualizationXML) VisualizationMapper.mapXML(visualizationXML, output); + if (visualizationXML) VisualizationMapper.mapXML(visualizationXML, output); + + const roomVisualizationXML = await this.getRoomVisualizationXML(habboAssetSWF, snakeCase); + + if (roomVisualizationXML) RoomVisualizationMapper.mapXML(roomVisualizationXML, output); return output; }