Begin HabboRoomContent converter

This commit is contained in:
Bill 2022-12-21 12:31:31 -05:00
parent e0a1800a83
commit b116ebd029
25 changed files with 801 additions and 42 deletions

View File

@ -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();

View File

@ -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;
}

View File

@ -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';

View File

@ -0,0 +1,4 @@
export interface IAssetRoomVisualizationData
{
}

View File

@ -0,0 +1 @@
export * from './IAssetRoomVisualizationData';

View File

@ -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);
}
}

View File

@ -4,4 +4,5 @@ export * from './IndexMapper';
export * from './LogicMapper';
export * from './ManifestMapper';
export * from './Mapper';
export * from './RoomVisualizationMapper';
export * from './VisualizationMapper';

View File

@ -4,4 +4,5 @@ export * from './index';
export * from './IndexXML';
export * from './logic';
export * from './manifest';
export * from './room-visualization';
export * from './visualization';

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1 @@
export * from './RoomVisualizationXML';

View File

@ -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';
@ -65,6 +65,15 @@ export class SWFUtilities
return await parseStringPromise(this.removeComments(binaryData.binaryData));
}
public static async getRoomAssetsXML(habboAssetSWF: HabboAssetSWF, snakeCase: boolean = false): Promise<any>
{
const binaryData = SWFUtilities.getBinaryData(habboAssetSWF, 'room_assets', false, snakeCase);
if (!binaryData) return null;
return await parseStringPromise(this.removeComments(binaryData.binaryData));
}
public static async getLogicXML(habboAssetSWF: HabboAssetSWF, snakeCase: boolean = false): Promise<any>
{
const binaryData = SWFUtilities.getBinaryData(habboAssetSWF, 'logic', true, snakeCase);
@ -78,6 +87,17 @@ export class SWFUtilities
{
const binaryData = SWFUtilities.getBinaryData(habboAssetSWF, 'visualization', true, snakeCase);
console.log(binaryData);
if (!binaryData) return null;
return await parseStringPromise(this.removeComments(binaryData.binaryData));
}
public static async getRoomVisualizationXML(habboAssetSWF: HabboAssetSWF, snakeCase: boolean = false): Promise<any>
{
const binaryData = SWFUtilities.getBinaryData(habboAssetSWF, 'room_visualization', false, snakeCase);
if (!binaryData) return null;
return await parseStringPromise(this.removeComments(binaryData.binaryData));
@ -174,6 +194,10 @@ export class SWFUtilities
}
}
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);
@ -186,6 +210,10 @@ export class SWFUtilities
if (visualizationXML) VisualizationMapper.mapXML(visualizationXML, output);
const roomVisualizationXML = await this.getRoomVisualizationXML(habboAssetSWF, snakeCase);
if (roomVisualizationXML) RoomVisualizationMapper.mapXML(roomVisualizationXML, output);
return output;
}
}