mirror of
https://github.com/billsonnn/nitro-converter.git
synced 2024-11-22 07:30:52 +01:00
Refactor
This commit is contained in:
parent
13cc7f601d
commit
85b7471772
16
.editorconfig
Normal file
16
.editorconfig
Normal file
@ -0,0 +1,16 @@
|
||||
# Editor configuration, see https://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.ts]
|
||||
quote_type = single
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
132
.eslintrc.json
Normal file
132
.eslintrc.json
Normal file
@ -0,0 +1,132 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2021": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 12,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"rules": {
|
||||
"indent": [
|
||||
"error",
|
||||
4,
|
||||
{
|
||||
"SwitchCase": 1
|
||||
}
|
||||
],
|
||||
"no-trailing-spaces": [
|
||||
"error",
|
||||
{
|
||||
"skipBlankLines": false,
|
||||
"ignoreComments": true
|
||||
}
|
||||
],
|
||||
"linebreak-style": [
|
||||
"off"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
],
|
||||
"semi": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"brace-style": [
|
||||
"error",
|
||||
"allman"
|
||||
],
|
||||
"object-curly-spacing": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"keyword-spacing": [
|
||||
"error",
|
||||
{
|
||||
"overrides":
|
||||
{
|
||||
"if":
|
||||
{
|
||||
"after": false
|
||||
},
|
||||
"for":
|
||||
{
|
||||
"after": false
|
||||
},
|
||||
"while":
|
||||
{
|
||||
"after": false
|
||||
},
|
||||
"switch":
|
||||
{
|
||||
"after": false
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-explicit-any": [
|
||||
"off"
|
||||
],
|
||||
"@typescript-eslint/explicit-module-boundary-types": [
|
||||
"off",
|
||||
{
|
||||
"allowedNames": [
|
||||
"getMessageArray"
|
||||
]
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/ban-ts-comment": [
|
||||
"off"
|
||||
],
|
||||
"@typescript-eslint/no-empty-function": [
|
||||
"error",
|
||||
{
|
||||
"allow": [
|
||||
"functions",
|
||||
"arrowFunctions",
|
||||
"generatorFunctions",
|
||||
"methods",
|
||||
"generatorMethods",
|
||||
"constructors"
|
||||
]
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"off"
|
||||
],
|
||||
"@typescript-eslint/no-inferrable-types": [
|
||||
"error",
|
||||
{
|
||||
"ignoreParameters": true,
|
||||
"ignoreProperties": true
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/ban-types": [
|
||||
"error",
|
||||
{
|
||||
"types":
|
||||
{
|
||||
"String": true,
|
||||
"Boolean": true,
|
||||
"Number": true,
|
||||
"Symbol": true,
|
||||
"{}": false,
|
||||
"Object": false,
|
||||
"object": false,
|
||||
"Function": false
|
||||
},
|
||||
"extendDefaults": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
16
.vscode/settings.json
vendored
Normal file
16
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"typescript.tsdk": "node_modules\\typescript\\lib",
|
||||
"typescript.preferences.importModuleSpecifier": "relative",
|
||||
"typescript.preferences.quoteStyle": "single",
|
||||
"typescript.format.placeOpenBraceOnNewLineForControlBlocks": true,
|
||||
"typescript.format.placeOpenBraceOnNewLineForFunctions": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": true,
|
||||
"source.organizeImports": true,
|
||||
},
|
||||
"emmet.showExpandedAbbreviation": "never",
|
||||
"git.ignoreLimitWarning": true,
|
||||
"files.eol": "\n",
|
||||
"files.insertFinalNewline": true,
|
||||
"files.trimFinalNewlines": true
|
||||
}
|
5808
package-lock.json
generated
5808
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
17
package.json
17
package.json
@ -4,13 +4,12 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"start:dev": "ts-node-dev --respawn --transpile-only src/Main.ts"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@gizeta/swf-reader": "^1.0.0",
|
||||
"@types/node": "^14.14.22",
|
||||
"bytebuffer": "^5.0.1",
|
||||
"concat-frames": "^1.0.3",
|
||||
"free-tex-packer-core": "^0.3.2",
|
||||
@ -19,11 +18,23 @@
|
||||
"lodash": "^4.17.20",
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-gzip": "^1.1.2",
|
||||
"ora": "^5.3.0",
|
||||
"png-stream": "^1.0.5",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"stream-to-array": "^2.3.0",
|
||||
"tsyringe": "^4.4.0",
|
||||
"xml2js": "^0.4.23"
|
||||
},
|
||||
"devDependencies": {}
|
||||
"devDependencies": {
|
||||
"@types/bytebuffer": "^5.0.42",
|
||||
"@types/node": "^14.14.28",
|
||||
"@types/node-fetch": "^2.5.8",
|
||||
"@types/xml2js": "^0.4.8",
|
||||
"@typescript-eslint/eslint-plugin": "^4.15.1",
|
||||
"@typescript-eslint/parser": "^4.15.1",
|
||||
"eslint": "^7.20.0",
|
||||
"ts-node": "^9.1.1",
|
||||
"ts-node-dev": "^1.1.1",
|
||||
"typescript": "^4.1.5"
|
||||
}
|
||||
}
|
||||
|
51
src/Main.ts
51
src/Main.ts
@ -1,34 +1,47 @@
|
||||
import "reflect-metadata";
|
||||
import Configuration from "./config/Configuration";
|
||||
import {container} from "tsyringe";
|
||||
import FigureConverter from "./figure/FigureConverter";
|
||||
import FurnitureConverter from "./furniture/FurnitureConverter";
|
||||
import PetConverter from "./pet/PetConverter";
|
||||
import EffectConverter from "./effect/EffectConverter";
|
||||
import 'reflect-metadata';
|
||||
import { container } from 'tsyringe';
|
||||
import { BundleProvider } from './common/bundle/BundleProvider';
|
||||
import { Configuration } from './common/config/Configuration';
|
||||
import { FurnitureConverter } from './converters/furniture/FurnitureConverter';
|
||||
import { PetConverter } from './converters/pet/PetConverter';
|
||||
import { Mapper } from './mapping/mappers/asset/Mapper';
|
||||
|
||||
(async () => {
|
||||
(async () =>
|
||||
{
|
||||
const config = container.resolve(Configuration);
|
||||
await config.init();
|
||||
|
||||
if (config.getBoolean("convert.figure")) {
|
||||
const figureConverter = container.resolve(FigureConverter);
|
||||
await figureConverter.convertAsync();
|
||||
}
|
||||
const prohibitedSizes = (config.getValue('prohibited.sizes') || '').split(',');
|
||||
const prohibitedSizesAsset = [];
|
||||
|
||||
if (config.getBoolean("convert.furniture")) {
|
||||
for(const prohibitedSize of prohibitedSizes) prohibitedSizesAsset.push('_' + prohibitedSize + '_');
|
||||
|
||||
Mapper.PROHIBITED_SIZES = prohibitedSizes;
|
||||
BundleProvider.PROHIBITED_SIZES = prohibitedSizesAsset;
|
||||
|
||||
// if(config.getBoolean('convert.figure'))
|
||||
// {
|
||||
// const figureConverter = container.resolve(FigureConverter);
|
||||
// await figureConverter.convertAsync();
|
||||
// }
|
||||
|
||||
if(config.getBoolean('convert.furniture'))
|
||||
{
|
||||
const furnitureConverter = container.resolve(FurnitureConverter);
|
||||
await furnitureConverter.convertAsync();
|
||||
}
|
||||
|
||||
if (config.getBoolean("convert.pet")) {
|
||||
if(config.getBoolean('convert.pet'))
|
||||
{
|
||||
const petConverter = container.resolve(PetConverter);
|
||||
await petConverter.convertAsync();
|
||||
}
|
||||
|
||||
if (config.getBoolean("convert.effect")) {
|
||||
const effectConverter = container.resolve(EffectConverter);
|
||||
await effectConverter.convertAsync();
|
||||
}
|
||||
// if(config.getBoolean('convert.effect'))
|
||||
// {
|
||||
// const effectConverter = container.resolve(EffectConverter);
|
||||
// await effectConverter.convertAsync();
|
||||
// }
|
||||
|
||||
console.log('finished!');
|
||||
})()
|
||||
})();
|
||||
|
@ -1,113 +0,0 @@
|
||||
import HabboAssetSWF from "../swf/HabboAssetSWF";
|
||||
import BundleTypes from "./BundleTypes";
|
||||
import SymbolClassTag from "../swf/tags/SymbolClassTag";
|
||||
import ImageTag from "../swf/tags/ImageTag";
|
||||
import {singleton} from "tsyringe";
|
||||
|
||||
const {packAsync} = require('free-tex-packer-core');
|
||||
|
||||
@singleton()
|
||||
export default class BundleProvider {
|
||||
public static imageSource: Map<string, string> = new Map<string, string>();
|
||||
|
||||
public async generateSpriteSheet(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string): Promise<BundleTypes | null> {
|
||||
const tagList: Array<SymbolClassTag> = habboAssetSWF.symbolTags();
|
||||
const names: Array<string> = new Array<string>();
|
||||
const tags: Array<number> = new Array<number>();
|
||||
for (const tag of tagList) {
|
||||
names.push(...tag.names);
|
||||
tags.push(...tag.tags);
|
||||
}
|
||||
|
||||
const images: Array<{ path: string, contents: Buffer }> = new Array<{ path: string, contents: Buffer }>();
|
||||
|
||||
const imageTags: Array<ImageTag> = habboAssetSWF.imageTags();
|
||||
for (const imageTag of imageTags) {
|
||||
if (tags.includes(imageTag.characterID)) {
|
||||
for (let i = 0; i < tags.length; i++) {
|
||||
if (tags[i] == imageTag.characterID) {
|
||||
if (
|
||||
(names[i].includes("_64_") && type === "furniture") ||
|
||||
(names[i].includes("_icon_") && type === "furniture") ||
|
||||
(names[i].includes("_h_") && (type === "figure" || type === "effect")) ||
|
||||
(names[i].includes("_64_") && type === "pet")) {
|
||||
|
||||
if (names[i] !== imageTag.className) {
|
||||
BundleProvider.imageSource.set(names[i].substring(habboAssetSWF.getDocumentClass().length + 1), imageTag.className.substring(habboAssetSWF.getDocumentClass().length + 1));
|
||||
if ((imageTag.className.includes("_32_") && type === "furniture") ||
|
||||
(imageTag.className.includes("_sh_") && (type === "figure" || type === "effect")) ||
|
||||
(imageTag.className.includes("_32_") && type === "pet")) {
|
||||
images.push({
|
||||
path: imageTag.className,
|
||||
contents: imageTag.imgData
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((imageTag.className.includes("_64_") && type === "furniture") ||
|
||||
(imageTag.className.includes("_1_") && type === "furniture") ||
|
||||
(imageTag.className.includes("_icon_") && type === "furniture") ||
|
||||
(imageTag.className.includes("_h_") && (type === "figure" || type === "effect")) ||
|
||||
(imageTag.className.includes("_64_") && type === "pet")) {
|
||||
images.push({
|
||||
path: imageTag.className,
|
||||
contents: imageTag.imgData
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (images.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return await this.packImages(habboAssetSWF.getDocumentClass(), outputFolder + "/", images);
|
||||
}
|
||||
|
||||
async packImages(documentClass: string, outputFolder: string, images: Array<{ path: string, contents: Buffer }>): Promise<BundleTypes | null> {
|
||||
let options = {
|
||||
textureName: documentClass,
|
||||
width: 3072,
|
||||
height: 2048,
|
||||
fixedSize: false,
|
||||
allowRotation: true,
|
||||
detectIdentical: true,
|
||||
allowTrim: true,
|
||||
exporter: "Pixi"
|
||||
};
|
||||
|
||||
const archiveType: BundleTypes = {} as any;
|
||||
const imageData: {
|
||||
name: string,
|
||||
buffer: Buffer
|
||||
} = {} as any;
|
||||
|
||||
try {
|
||||
const files = await packAsync(images, options);
|
||||
for (let item of files) {
|
||||
if (item.name.endsWith(".json")) {
|
||||
archiveType.spriteSheetType = JSON.parse(item.buffer.toString('utf8'));
|
||||
} else {
|
||||
imageData.buffer = item.buffer;
|
||||
imageData.name = item.name;
|
||||
}
|
||||
}
|
||||
|
||||
if (archiveType.spriteSheetType === null) throw new Error("Failed to parse SpriteSheet. " + images[0].path);
|
||||
} catch (error) {
|
||||
console.log("Image Packing Error: ");
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
if (archiveType.spriteSheetType !== null) {
|
||||
archiveType.spriteSheetType.meta.image = imageData.name;
|
||||
archiveType.imageData = imageData;
|
||||
}
|
||||
|
||||
return archiveType;
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
export default interface BundleTypes {
|
||||
spriteSheetType: SpriteSheetType,
|
||||
imageData: {
|
||||
name: string,
|
||||
buffer: Buffer
|
||||
}
|
||||
}
|
||||
|
||||
export interface SpriteSheetType {
|
||||
frames: SpriteSheetFrames,
|
||||
meta: SpriteSheetMeta
|
||||
}
|
||||
|
||||
export interface SpriteSheetFrames {
|
||||
[key: string]: SpriteSheetFrame
|
||||
}
|
||||
|
||||
export interface SpriteSheetFrame {
|
||||
frame: SpriteSheetFrameDimensions,
|
||||
rotated: boolean,
|
||||
trimmed: boolean,
|
||||
spriteSourceSize: SpriteSourceSize
|
||||
sourceSize: SourceSize,
|
||||
pivot: FramePivot
|
||||
}
|
||||
|
||||
export interface FramePivot {
|
||||
x: number,
|
||||
y: number
|
||||
}
|
||||
|
||||
export interface SourceSize {
|
||||
w: number,
|
||||
h: number
|
||||
}
|
||||
|
||||
export interface SpriteSourceSize {
|
||||
x: number,
|
||||
y: number,
|
||||
w: number,
|
||||
h: number
|
||||
}
|
||||
|
||||
export interface SpriteSheetFrameDimensions {
|
||||
x: number,
|
||||
y: number,
|
||||
w: number,
|
||||
h: number
|
||||
}
|
||||
|
||||
export interface SpriteSheetMeta {
|
||||
app: string,
|
||||
version: string,
|
||||
image: string,
|
||||
format: string,
|
||||
size: SpriteSheetSize,
|
||||
scale: number
|
||||
}
|
||||
|
||||
export interface SpriteSheetSize {
|
||||
w: number,
|
||||
h: number
|
||||
}
|
144
src/common/bundle/BundleProvider.ts
Normal file
144
src/common/bundle/BundleProvider.ts
Normal file
@ -0,0 +1,144 @@
|
||||
import { packAsync } from 'free-tex-packer-core';
|
||||
import { singleton } from 'tsyringe';
|
||||
import { HabboAssetSWF } from '../../swf/HabboAssetSWF';
|
||||
import { Configuration } from '../config/Configuration';
|
||||
import { SpriteBundle } from './SpriteBundle';
|
||||
|
||||
@singleton()
|
||||
export class BundleProvider
|
||||
{
|
||||
public static PROHIBITED_SIZES: string[] = [];
|
||||
|
||||
public static imageSource: Map<string, string> = new Map();
|
||||
|
||||
constructor(private readonly _configuration: Configuration)
|
||||
{}
|
||||
|
||||
public async generateSpriteSheet(habboAssetSWF: HabboAssetSWF): Promise<SpriteBundle>
|
||||
{
|
||||
const tagList = habboAssetSWF.symbolTags();
|
||||
const names: string[] = [];
|
||||
const tags: number[] = [];
|
||||
|
||||
for(const tag of tagList)
|
||||
{
|
||||
names.push(...tag.names);
|
||||
tags.push(...tag.tags);
|
||||
}
|
||||
|
||||
const images: { path: string, contents: Buffer }[] = [];
|
||||
|
||||
const imageTags = habboAssetSWF.imageTags();
|
||||
|
||||
for(const imageTag of imageTags)
|
||||
{
|
||||
if(tags.includes(imageTag.characterID))
|
||||
{
|
||||
for(let i = 0; i < tags.length; i++)
|
||||
{
|
||||
if(tags[i] != imageTag.characterID) continue;
|
||||
|
||||
if(names[i] == imageTag.className) continue;
|
||||
|
||||
let isProhibited = false;
|
||||
|
||||
for(const size of BundleProvider.PROHIBITED_SIZES)
|
||||
{
|
||||
if(imageTag.className.indexOf(size) >= 0)
|
||||
{
|
||||
isProhibited = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(isProhibited) continue;
|
||||
|
||||
BundleProvider.imageSource.set(names[i].substring(habboAssetSWF.getDocumentClass().length + 1), imageTag.className.substring(habboAssetSWF.getDocumentClass().length + 1));
|
||||
|
||||
images.push({
|
||||
path: imageTag.className,
|
||||
contents: imageTag.imgData
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let isProhibited = false;
|
||||
|
||||
for(const size of BundleProvider.PROHIBITED_SIZES)
|
||||
{
|
||||
if(imageTag.className.indexOf(size) >= 0)
|
||||
{
|
||||
isProhibited = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(isProhibited) continue;
|
||||
|
||||
images.push({
|
||||
path: imageTag.className,
|
||||
contents: imageTag.imgData
|
||||
});
|
||||
}
|
||||
|
||||
if(!images.length) return null;
|
||||
|
||||
return await this.packImages(habboAssetSWF.getDocumentClass(), images);
|
||||
}
|
||||
|
||||
async packImages(documentClass: string, images: { path: string, contents: Buffer }[]): Promise<SpriteBundle>
|
||||
{
|
||||
try
|
||||
{
|
||||
const files = await packAsync(images, {
|
||||
textureName: documentClass,
|
||||
width: 3072,
|
||||
height: 2048,
|
||||
fixedSize: false,
|
||||
allowRotation: true,
|
||||
detectIdentical: true,
|
||||
allowTrim: true,
|
||||
//@ts-ignore
|
||||
exporter: 'Pixi'
|
||||
});
|
||||
|
||||
const bundle = new SpriteBundle();
|
||||
|
||||
for(const item of files)
|
||||
{
|
||||
if(item.name.endsWith('.json'))
|
||||
{
|
||||
bundle.spritesheet = JSON.parse(item.buffer.toString('utf8'));
|
||||
|
||||
delete bundle.spritesheet.meta.app;
|
||||
delete bundle.spritesheet.meta.version;
|
||||
}
|
||||
else
|
||||
{
|
||||
bundle.imageData = {
|
||||
name: item.name,
|
||||
buffer: item.buffer
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if(!bundle.spritesheet) throw new Error('Failed to parse SpriteSheet. ' + images[0].path);
|
||||
|
||||
if((bundle.spritesheet !== undefined) && (bundle.imageData !== undefined))
|
||||
{
|
||||
bundle.spritesheet.meta.image = bundle.imageData.name;
|
||||
}
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
console.error('Image Packing Error', error);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
27
src/common/bundle/SpriteBundle.ts
Normal file
27
src/common/bundle/SpriteBundle.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { ISpritesheetData } from '../../mapping/json';
|
||||
|
||||
export class SpriteBundle
|
||||
{
|
||||
private _spritesheet: ISpritesheetData;
|
||||
private _imageData: { name: string, buffer: Buffer};
|
||||
|
||||
public get spritesheet(): ISpritesheetData
|
||||
{
|
||||
return this._spritesheet;
|
||||
}
|
||||
|
||||
public set spritesheet(spritesheet: ISpritesheetData)
|
||||
{
|
||||
this._spritesheet = spritesheet;
|
||||
}
|
||||
|
||||
public get imageData(): { name: string, buffer: Buffer}
|
||||
{
|
||||
return this._imageData;
|
||||
}
|
||||
|
||||
public set imageData(imageData: { name: string, buffer: Buffer })
|
||||
{
|
||||
this._imageData = imageData;
|
||||
}
|
||||
}
|
61
src/common/config/Configuration.ts
Normal file
61
src/common/config/Configuration.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import { singleton } from 'tsyringe';
|
||||
import * as configuration from '../../configuration.json';
|
||||
import { FileUtilities } from '../../utils/FileUtilities';
|
||||
|
||||
@singleton()
|
||||
export class Configuration
|
||||
{
|
||||
private readonly _config: Map<string, string>;
|
||||
|
||||
constructor()
|
||||
{
|
||||
this._config = new Map<string, string>();
|
||||
}
|
||||
|
||||
public async init(): Promise<void>
|
||||
{
|
||||
for(const key of Object.keys(configuration)) this._config.set(key, configuration[key]);
|
||||
}
|
||||
|
||||
public async loadExternalVariables(): Promise<void>
|
||||
{
|
||||
const url = this.getValue('external_vars.url');
|
||||
|
||||
try
|
||||
{
|
||||
const content = await FileUtilities.readFileAsString(url);
|
||||
const config: string[] = content.split('\n');
|
||||
|
||||
for(const configEntry of config)
|
||||
{
|
||||
const configEntrySplit = configEntry.split('=');
|
||||
const configKey = configEntrySplit[0];
|
||||
const configValue = configEntrySplit[1];
|
||||
|
||||
this._config.set(configKey, configValue);
|
||||
}
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
public getBoolean(key: string): boolean
|
||||
{
|
||||
return this._config.get(key) === '1';
|
||||
}
|
||||
|
||||
public getValue(key: string, value: string = ''): string
|
||||
{
|
||||
if(this._config.has(key))
|
||||
{
|
||||
// @ts-ignore
|
||||
return this._config.get(key);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
102
src/common/converters/SWFConverter.ts
Normal file
102
src/common/converters/SWFConverter.ts
Normal file
@ -0,0 +1,102 @@
|
||||
import { wrap } from 'bytebuffer';
|
||||
import { parseStringPromise } from 'xml2js';
|
||||
import { HabboAssetSWF } from '../../swf/HabboAssetSWF';
|
||||
import { DefineBinaryDataTag } from '../../swf/tags/DefineBinaryDataTag';
|
||||
|
||||
export class SWFConverter
|
||||
{
|
||||
private static getBinaryData(habboAssetSWF: HabboAssetSWF, type: string, documentNameTwice: boolean): DefineBinaryDataTag
|
||||
{
|
||||
let binaryName = habboAssetSWF.getFullClassName(type, documentNameTwice);
|
||||
let tag = habboAssetSWF.getBinaryTagByName(binaryName);
|
||||
|
||||
if(!tag)
|
||||
{
|
||||
binaryName = habboAssetSWF.getFullClassNameSnake(type, documentNameTwice, true);
|
||||
tag = habboAssetSWF.getBinaryTagByName(binaryName);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
protected static getPalette(habboAssetSWF: HabboAssetSWF, paletteName: string): [ number, number, number ][]
|
||||
{
|
||||
const binaryData = SWFConverter.getBinaryData(habboAssetSWF, paletteName, false);
|
||||
|
||||
if(!binaryData || !binaryData.binaryDataBuffer) return null;
|
||||
|
||||
const byteBuffer = wrap(binaryData.binaryDataBuffer);
|
||||
|
||||
const paletteColors: [ number, number, number ][] = [];
|
||||
|
||||
try
|
||||
{
|
||||
let R = 0;
|
||||
let G = 0;
|
||||
let B = 0;
|
||||
let counter = 1;
|
||||
|
||||
while((binaryData.binaryDataBuffer.length - byteBuffer.offset) > 0)
|
||||
{
|
||||
if(counter == 1) R = byteBuffer.readUint8();
|
||||
|
||||
else if(counter == 2) G = byteBuffer.readUint8();
|
||||
|
||||
else if(counter == 3)
|
||||
{
|
||||
B = byteBuffer.readUint8();
|
||||
paletteColors.push([ R, G, B ]);
|
||||
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
return paletteColors;
|
||||
}
|
||||
|
||||
catch (err)
|
||||
{
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static async getAssetsXML(habboAssetSWF: HabboAssetSWF): Promise<any>
|
||||
{
|
||||
const binaryData = SWFConverter.getBinaryData(habboAssetSWF, 'assets', true);
|
||||
|
||||
if(!binaryData) return null;
|
||||
|
||||
return await parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
|
||||
protected static async getLogicXML(habboAssetSWF: HabboAssetSWF): Promise<any>
|
||||
{
|
||||
const binaryData = SWFConverter.getBinaryData(habboAssetSWF, 'logic', true);
|
||||
|
||||
if(!binaryData) return null;
|
||||
|
||||
return await parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
|
||||
protected static async getIndexXML(habboAssetSWF: HabboAssetSWF): Promise<any>
|
||||
{
|
||||
const binaryData = SWFConverter.getBinaryData(habboAssetSWF, 'index', false);
|
||||
|
||||
if(!binaryData) return null;
|
||||
|
||||
return await parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
|
||||
protected static async getVisualizationXML(habboAssetSWF: HabboAssetSWF): Promise<any>
|
||||
{
|
||||
const binaryData = SWFConverter.getBinaryData(habboAssetSWF, 'visualization', true);
|
||||
|
||||
if(!binaryData) return null;
|
||||
|
||||
return await parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
{
|
||||
"output.folder.furniture": "/home/user/WebstormProjects/sites/assets.nitro.se/game/dcr/furniture-test/",
|
||||
"output.folder.figure": "/home/user/WebstormProjects/sites/assets.nitro.se/game/gordon/figure-test/",
|
||||
"output.folder.effect": "/home/user/WebstormProjects/sites/assets.nitro.se/game/gordon/effect-test/",
|
||||
"output.folder.pet": "/home/user/WebstormProjects/sites/assets.nitro.se/game/gordon/pet-test/",
|
||||
"furnidata.url": "http://assets.nitro.se/game/harmony/furnidata.xml",
|
||||
"figuremap.url": "http://assets.nitro.se/game/gordon/figuremap.xml",
|
||||
"effectmap.url": "http://assets.nitro.se/game/gordon/PRODUCTION-201701242205-837386173/effectmap.xml",
|
||||
"external_vars.url": "http://assets.nitro.se/game/gamedata/external_variables.txt",
|
||||
"dynamic.download.url.furniture": "/home/user/WebstormProjects/sites/assets.nitro.se/game/harmony/hof_furni/%className%.swf",
|
||||
"dynamic.download.url.figure": "/home/user/WebstormProjects/sites/assets.nitro.se/game/gordon/PRODUCTION-201701242205-837386173/%className%.swf",
|
||||
"dynamic.download.url.effect": "/home/user/WebstormProjects/sites/assets.nitro.se/game/gordon/PRODUCTION-201701242205-837386173/%className%.swf",
|
||||
"dynamic.download.url.pet": "/home/user/WebstormProjects/sites/assets.nitro.se/game/gordon/PRODUCTION-201701242205-837386173/%className%.swf",
|
||||
"convert.furniture": "1",
|
||||
"convert.figure": "0",
|
||||
"convert.effect": "0",
|
||||
"convert.pet": "0",
|
||||
"figure.rotation.enabled": "0",
|
||||
"figure.skip.non-existing.asset.images": "0"
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
import {singleton} from "tsyringe";
|
||||
|
||||
const fs = require('fs/promises');
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
const config = require('../config.json');
|
||||
|
||||
@singleton()
|
||||
export default class Configuration {
|
||||
|
||||
private readonly _config: Map<string, string>;
|
||||
|
||||
constructor() {
|
||||
this._config = new Map<string, string>();
|
||||
}
|
||||
|
||||
async init() {
|
||||
for (const key of Object.keys(config)) {
|
||||
this._config.set(key, config[key]);
|
||||
}
|
||||
}
|
||||
|
||||
public getBoolean(key: string): boolean {
|
||||
return this._config.get(key) === "1";
|
||||
}
|
||||
|
||||
public getValue(key: string, value: string = ""): string {
|
||||
if (this._config.has(key)) {
|
||||
// @ts-ignore
|
||||
return this._config.get(key);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public async loadExternalVariables(): Promise<void> {
|
||||
const url = this.getValue("external_vars.url");
|
||||
const fetchData = await fetch(url);
|
||||
const textData = await fetchData.text();
|
||||
|
||||
const config: string[] = textData.split("\n");
|
||||
for (const configEntry of config) {
|
||||
const configEntrySplit = configEntry.split("=");
|
||||
const configKey = configEntrySplit[0];
|
||||
const configValue = configEntrySplit[1];
|
||||
|
||||
this._config.set(configKey, configValue);
|
||||
}
|
||||
}
|
||||
}
|
19
src/configuration.json.example
Normal file
19
src/configuration.json.example
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"output.folder.furniture": "/converted-assets/furniture/",
|
||||
"output.folder.figure": "/converted-assets/figure/",
|
||||
"output.folder.effect": "/converted-assets/effect/",
|
||||
"output.folder.pet": "/converted-assets/pet/",
|
||||
"furnidata.url": "/gamedata/json/furnidata",
|
||||
"figuremap.url": "/gamedata/figuremap.xml",
|
||||
"effectmap.url": "/gamedata/effectmap.xml",
|
||||
"external_vars.url": "/gamedata/external_variables.txt",
|
||||
"dynamic.download.url.furniture": "/dcr/hof_furni/%className%.swf",
|
||||
"dynamic.download.url.figure": "/gordon/PRODUCTION/%className%.swf",
|
||||
"dynamic.download.url.effect": "/gordon/PRODUCTION/%className%.swf",
|
||||
"dynamic.download.url.pet": "/gordon/PRODUCTION/%className%.swf",
|
||||
"convert.furniture": "1",
|
||||
"convert.figure": "0",
|
||||
"convert.effect": "0",
|
||||
"convert.pet": "1",
|
||||
"prohibited.sizes": "32,sh"
|
||||
}
|
130
src/converters/furniture/FurnitureConverter.ts
Normal file
130
src/converters/furniture/FurnitureConverter.ts
Normal file
@ -0,0 +1,130 @@
|
||||
import { writeFile } from 'fs/promises';
|
||||
import * as ora from 'ora';
|
||||
import { singleton } from 'tsyringe';
|
||||
import { BundleProvider } from '../../common/bundle/BundleProvider';
|
||||
import { SpriteBundle } from '../../common/bundle/SpriteBundle';
|
||||
import { Configuration } from '../../common/config/Configuration';
|
||||
import { SWFConverter } from '../../common/converters/SWFConverter';
|
||||
import { IAssetData } from '../../mapping/json';
|
||||
import { AssetMapper, IndexMapper, LogicMapper, VisualizationMapper } from '../../mapping/mappers';
|
||||
import { HabboAssetSWF } from '../../swf/HabboAssetSWF';
|
||||
import File from '../../utils/File';
|
||||
import Logger from '../../utils/Logger';
|
||||
import NitroBundle from '../../utils/NitroBundle';
|
||||
import { FurnitureDownloader } from './FurnitureDownloader';
|
||||
|
||||
@singleton()
|
||||
export class FurnitureConverter extends SWFConverter
|
||||
{
|
||||
constructor(
|
||||
private readonly _furniDownloader: FurnitureDownloader,
|
||||
private readonly _configuration: Configuration,
|
||||
private readonly _bundleProvider: BundleProvider,
|
||||
private readonly _logger: Logger)
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public async convertAsync(): Promise<void>
|
||||
{
|
||||
const now = Date.now();
|
||||
|
||||
const spinner = ora('Preparing Furniture').start();
|
||||
|
||||
const outputFolder = new File(this._configuration.getValue('output.folder.furniture'));
|
||||
|
||||
if(!outputFolder.isDirectory())
|
||||
{
|
||||
spinner.text = `Creating Folder: ${ outputFolder.path }`;
|
||||
|
||||
spinner.render();
|
||||
|
||||
outputFolder.mkdirs();
|
||||
}
|
||||
|
||||
await this._furniDownloader.download(async (habboAssetSwf: HabboAssetSWF) =>
|
||||
{
|
||||
spinner.text = 'Parsing Furniture: ' + habboAssetSwf.getDocumentClass();
|
||||
|
||||
spinner.render();
|
||||
|
||||
try
|
||||
{
|
||||
const spriteBundle = await this._bundleProvider.generateSpriteSheet(habboAssetSwf);
|
||||
|
||||
await this.fromHabboAsset(habboAssetSwf, outputFolder.path, 'furniture', spriteBundle);
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
|
||||
spinner.succeed(`Furniture Finished in ${ Date.now() - now }ms`);
|
||||
}
|
||||
|
||||
private async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, spriteBundle: SpriteBundle): Promise<void>
|
||||
{
|
||||
const assetData = await this.mapXML2JSON(habboAssetSWF, 'furniture');
|
||||
|
||||
if(!assetData) return;
|
||||
|
||||
const name = habboAssetSWF.getDocumentClass();
|
||||
const path = outputFolder + '/' + name + '.nitro';
|
||||
const nitroBundle = new NitroBundle();
|
||||
|
||||
nitroBundle.addFile((name + '.json'), Buffer.from(JSON.stringify(assetData)));
|
||||
|
||||
if(spriteBundle && (spriteBundle.spritesheet !== undefined))
|
||||
{
|
||||
if(spriteBundle.spritesheet && spriteBundle.imageData)
|
||||
{
|
||||
assetData.spritesheet = spriteBundle.spritesheet;
|
||||
|
||||
nitroBundle.addFile(spriteBundle.imageData.name, spriteBundle.imageData.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
const buffer = await nitroBundle.toBufferAsync();
|
||||
|
||||
await writeFile(path, buffer);
|
||||
}
|
||||
|
||||
private async mapXML2JSON(habboAssetSWF: HabboAssetSWF, assetType: string): Promise<IAssetData>
|
||||
{
|
||||
if(!habboAssetSWF) return null;
|
||||
|
||||
const assetData: IAssetData = {};
|
||||
|
||||
assetData.type = assetType;
|
||||
|
||||
try
|
||||
{
|
||||
const indexXML = await FurnitureConverter.getIndexXML(habboAssetSWF);
|
||||
|
||||
if(indexXML) IndexMapper.mapXML(indexXML, assetData);
|
||||
|
||||
const assetXML = await FurnitureConverter.getAssetsXML(habboAssetSWF);
|
||||
|
||||
if(assetXML) AssetMapper.mapXML(assetXML, assetData);
|
||||
|
||||
const logicXML = await FurnitureConverter.getLogicXML(habboAssetSWF);
|
||||
|
||||
if(logicXML) LogicMapper.mapXML(logicXML, assetData);
|
||||
|
||||
const visualizationXML = await FurnitureConverter.getVisualizationXML(habboAssetSWF);
|
||||
|
||||
if(visualizationXML) VisualizationMapper.mapXML(visualizationXML, assetData);
|
||||
|
||||
return assetData;
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
146
src/converters/furniture/FurnitureDownloader.ts
Normal file
146
src/converters/furniture/FurnitureDownloader.ts
Normal file
@ -0,0 +1,146 @@
|
||||
import { singleton } from 'tsyringe';
|
||||
import { Configuration } from '../../common/config/Configuration';
|
||||
import { IFurnitureData } from '../../mapping/json';
|
||||
import { HabboAssetSWF } from '../../swf/HabboAssetSWF';
|
||||
import File from '../../utils/File';
|
||||
import { FileUtilities } from '../../utils/FileUtilities';
|
||||
import Logger from '../../utils/Logger';
|
||||
|
||||
@singleton()
|
||||
export class FurnitureDownloader
|
||||
{
|
||||
constructor(
|
||||
private readonly _configuration: Configuration,
|
||||
private readonly _logger: Logger)
|
||||
{}
|
||||
|
||||
public async download(callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise<void>): Promise<void>
|
||||
{
|
||||
try
|
||||
{
|
||||
let count = 0;
|
||||
|
||||
const furniData = await this.parseFurniData();
|
||||
const classNames: string[] = [];
|
||||
|
||||
const outputFolder = new File(this._configuration.getValue('output.folder.furniture'));
|
||||
|
||||
if(!outputFolder.isDirectory()) outputFolder.mkdirs();
|
||||
|
||||
if(furniData.roomitemtypes !== undefined)
|
||||
{
|
||||
if(furniData.roomitemtypes.furnitype !== undefined)
|
||||
{
|
||||
for(const furniType of furniData.roomitemtypes.furnitype)
|
||||
{
|
||||
const className = furniType.classname.split('*')[0];
|
||||
const revision = furniType.revision;
|
||||
|
||||
if(count === 3) return;
|
||||
|
||||
if(classNames.indexOf(className) >= 0) continue;
|
||||
|
||||
classNames.push(className);
|
||||
|
||||
try
|
||||
{
|
||||
await this.extractFurniture(revision, className, callback);
|
||||
|
||||
count ++;
|
||||
}
|
||||
|
||||
catch(error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(furniData.wallitemtypes !== undefined)
|
||||
{
|
||||
if(furniData.wallitemtypes.furnitype !== undefined)
|
||||
{
|
||||
for(const furniType of furniData.wallitemtypes.furnitype)
|
||||
{
|
||||
const className = furniType.classname.split('*')[0];
|
||||
const revision = furniType.revision;
|
||||
|
||||
if(classNames.indexOf(className) >= 0) continue;
|
||||
|
||||
classNames.push(className);
|
||||
|
||||
try
|
||||
{
|
||||
await this.extractFurniture(revision, className, callback);
|
||||
}
|
||||
|
||||
catch(error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
public async parseFurniData(): Promise<IFurnitureData>
|
||||
{
|
||||
const url = this._configuration.getValue('furnidata.url');
|
||||
|
||||
if(!url || !url.length) return null;
|
||||
|
||||
try
|
||||
{
|
||||
const content = await FileUtilities.readFileAsString(url);
|
||||
|
||||
if(!content || !content.length) return null;
|
||||
|
||||
return (JSON.parse(content) as IFurnitureData);
|
||||
}
|
||||
|
||||
catch(error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
public async extractFurniture(revision: number, className: string, callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise<void>): Promise<void>
|
||||
{
|
||||
let url = this._configuration.getValue('dynamic.download.url.furniture');
|
||||
|
||||
if(!url || !url.length) return;
|
||||
|
||||
url = url.replace('%revision%', revision.toString());
|
||||
url = url.replace('%className%', className);
|
||||
|
||||
try
|
||||
{
|
||||
const buffer = await FileUtilities.readFileAsBuffer(url);
|
||||
|
||||
if(!buffer) return;
|
||||
|
||||
const newHabboAssetSWF = new HabboAssetSWF(buffer);
|
||||
|
||||
await newHabboAssetSWF.setupAsync();
|
||||
|
||||
await callback(newHabboAssetSWF, className);
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
145
src/converters/pet/PetConverter.ts
Normal file
145
src/converters/pet/PetConverter.ts
Normal file
@ -0,0 +1,145 @@
|
||||
import { writeFile } from 'fs/promises';
|
||||
import { singleton } from 'tsyringe';
|
||||
import { BundleProvider } from '../../common/bundle/BundleProvider';
|
||||
import { SpriteBundle } from '../../common/bundle/SpriteBundle';
|
||||
import { Configuration } from '../../common/config/Configuration';
|
||||
import { SWFConverter } from '../../common/converters/SWFConverter';
|
||||
import { IAssetData } from '../../mapping/json';
|
||||
import { AssetMapper, IndexMapper, LogicMapper, VisualizationMapper } from '../../mapping/mappers';
|
||||
import { HabboAssetSWF } from '../../swf/HabboAssetSWF';
|
||||
import File from '../../utils/File';
|
||||
import Logger from '../../utils/Logger';
|
||||
import NitroBundle from '../../utils/NitroBundle';
|
||||
import { PetDownloader } from './PetDownloader';
|
||||
|
||||
@singleton()
|
||||
export class PetConverter extends SWFConverter
|
||||
{
|
||||
constructor(
|
||||
private readonly _petDownloader: PetDownloader,
|
||||
private readonly _config: Configuration,
|
||||
private readonly _bundleProvider: BundleProvider,
|
||||
private readonly _logger: Logger)
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public async convertAsync(): Promise<void>
|
||||
{
|
||||
const outputFolder = new File(this._config.getValue('output.folder.pet'));
|
||||
|
||||
if(!outputFolder.isDirectory()) outputFolder.mkdirs();
|
||||
|
||||
await this._petDownloader.download(async (habboAssetSwf: HabboAssetSWF) =>
|
||||
{
|
||||
console.log('Parsing Pet: ' + habboAssetSwf.getDocumentClass());
|
||||
|
||||
try
|
||||
{
|
||||
const spriteBundle = await this._bundleProvider.generateSpriteSheet(habboAssetSwf);
|
||||
|
||||
await this.fromHabboAsset(habboAssetSwf, outputFolder.path, 'pet', spriteBundle);
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, spriteBundle: SpriteBundle): Promise<void>
|
||||
{
|
||||
try
|
||||
{
|
||||
const assetData = await this.mapXML2JSON(habboAssetSWF, 'pet');
|
||||
|
||||
if(!assetData) return;
|
||||
|
||||
if(spriteBundle && (spriteBundle.spritesheet !== undefined)) assetData.spritesheet = spriteBundle.spritesheet;
|
||||
|
||||
const name = habboAssetSWF.getDocumentClass();
|
||||
const path = outputFolder + '/' + name + '.nitro';
|
||||
const nitroBundle = new NitroBundle();
|
||||
|
||||
nitroBundle.addFile((name + '.json'), Buffer.from(JSON.stringify(assetData)));
|
||||
|
||||
if(spriteBundle.imageData !== undefined)
|
||||
{
|
||||
nitroBundle.addFile(spriteBundle.imageData.name, spriteBundle.imageData.buffer);
|
||||
}
|
||||
|
||||
const buffer = await nitroBundle.toBufferAsync();
|
||||
|
||||
await writeFile(path, buffer);
|
||||
}
|
||||
|
||||
catch(err)
|
||||
{
|
||||
this._logger.logErrorAsync(err);
|
||||
}
|
||||
}
|
||||
|
||||
private async mapXML2JSON(habboAssetSWF: HabboAssetSWF, assetType: string): Promise<IAssetData>
|
||||
{
|
||||
if(!habboAssetSWF) return null;
|
||||
|
||||
const assetData: IAssetData = {};
|
||||
|
||||
assetData.type = assetType;
|
||||
|
||||
try
|
||||
{
|
||||
const indexXML = await PetConverter.getIndexXML(habboAssetSWF);
|
||||
|
||||
if(indexXML) IndexMapper.mapXML(indexXML, assetData);
|
||||
|
||||
const assetXML = await PetConverter.getAssetsXML(habboAssetSWF);
|
||||
|
||||
if(assetXML)
|
||||
{
|
||||
AssetMapper.mapXML(assetXML, assetData);
|
||||
|
||||
if(assetData.palettes !== undefined)
|
||||
{
|
||||
for(const paletteId in assetData.palettes)
|
||||
{
|
||||
const palette = assetData.palettes[paletteId];
|
||||
|
||||
const paletteColors = PetConverter.getPalette(habboAssetSWF, palette.source);
|
||||
|
||||
if(!paletteColors)
|
||||
{
|
||||
delete assetData.palettes[paletteId];
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const rgbs: [ number, number, number ][] = [];
|
||||
|
||||
for(const rgb of paletteColors) rgbs.push([ rgb[0], rgb[1], rgb[2] ]);
|
||||
|
||||
palette.rgb = rgbs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const logicXML = await PetConverter.getLogicXML(habboAssetSWF);
|
||||
|
||||
if(logicXML) LogicMapper.mapXML(logicXML, assetData);
|
||||
|
||||
const visualizationXML = await PetConverter.getVisualizationXML(habboAssetSWF);
|
||||
|
||||
if(visualizationXML) VisualizationMapper.mapXML(visualizationXML, assetData);
|
||||
|
||||
return assetData;
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
98
src/converters/pet/PetDownloader.ts
Normal file
98
src/converters/pet/PetDownloader.ts
Normal file
@ -0,0 +1,98 @@
|
||||
import { singleton } from 'tsyringe';
|
||||
import { Configuration } from '../../common/config/Configuration';
|
||||
import { HabboAssetSWF } from '../../swf/HabboAssetSWF';
|
||||
import { FileUtilities } from '../../utils/FileUtilities';
|
||||
import Logger from '../../utils/Logger';
|
||||
|
||||
@singleton()
|
||||
export class PetDownloader
|
||||
{
|
||||
constructor(
|
||||
private readonly _config: Configuration,
|
||||
private readonly _logger: Logger)
|
||||
{}
|
||||
|
||||
public async download(callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise<void>): Promise<void>
|
||||
{
|
||||
try
|
||||
{
|
||||
const petTypes = await this.parsePetTypes();
|
||||
const classNames: string[] = [];
|
||||
|
||||
for(const petType of petTypes)
|
||||
{
|
||||
if(classNames.indexOf(petType) >= 0) continue;
|
||||
|
||||
classNames.push(petType);
|
||||
|
||||
try
|
||||
{
|
||||
await this.extractPet(petType, callback);
|
||||
}
|
||||
|
||||
catch(error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
public async parsePetTypes(): Promise<string[]>
|
||||
{
|
||||
try
|
||||
{
|
||||
await this._config.loadExternalVariables();
|
||||
|
||||
const petTypes: string[] = [];
|
||||
|
||||
const pets = this._config.getValue('pet.configuration');
|
||||
|
||||
if(pets)
|
||||
{
|
||||
const types = pets.split(',');
|
||||
|
||||
for(const type of types) petTypes.push(type);
|
||||
}
|
||||
|
||||
return petTypes;
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
public async extractPet(className: string, callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise<void>): Promise<void>
|
||||
{
|
||||
let url = this._config.getValue('dynamic.download.url.pet');
|
||||
|
||||
if(!url || !url.length) return;
|
||||
|
||||
url = url.replace('%className%', className);
|
||||
|
||||
try
|
||||
{
|
||||
const buffer = await FileUtilities.readFileAsBuffer(url);
|
||||
const newHabboAssetSWF = new HabboAssetSWF(buffer);
|
||||
|
||||
await newHabboAssetSWF.setupAsync();
|
||||
await callback(newHabboAssetSWF, className);
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
import HabboAssetSWF from "../swf/HabboAssetSWF";
|
||||
import DefineBinaryDataTag from "../swf/tags/DefineBinaryDataTag";
|
||||
import {EffectJson} from "./mapper/EffectTypes";
|
||||
import BundleTypes from "../bundle/BundleTypes";
|
||||
import File from "../utils/File";
|
||||
import NitroBundle from "../utils/NitroBundle";
|
||||
import EffectDownloader from "./EffectDownloader";
|
||||
import EffectJsonMapper from "./mapper/EffectJsonMapper";
|
||||
import Configuration from "../config/Configuration";
|
||||
import BundleProvider from "../bundle/BundleProvider";
|
||||
import {singleton} from "tsyringe";
|
||||
|
||||
const xml2js = require('xml2js');
|
||||
const parser = new xml2js.Parser(/* options */);
|
||||
|
||||
const fs = require('fs').promises;
|
||||
|
||||
@singleton()
|
||||
export default class EffectConverter {
|
||||
constructor(
|
||||
private readonly _effectDownloader: EffectDownloader,
|
||||
private readonly _effectJsonMapper: EffectJsonMapper,
|
||||
private readonly _config: Configuration,
|
||||
private readonly _bundleProvider: BundleProvider) {
|
||||
}
|
||||
|
||||
private static getBinaryData(habboAssetSWF: HabboAssetSWF, type: string, documentNameTwice: boolean) {
|
||||
let binaryName: string = habboAssetSWF.getFullClassName(type, documentNameTwice);
|
||||
let tag = habboAssetSWF.getBinaryTagByName(binaryName);
|
||||
if (tag === null) {
|
||||
binaryName = habboAssetSWF.getFullClassNameSnake(type, documentNameTwice, true);
|
||||
tag = habboAssetSWF.getBinaryTagByName(binaryName);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
private static async getManifestXML(habboAssetSWF: HabboAssetSWF): Promise<any> {
|
||||
const binaryData: DefineBinaryDataTag | null = this.getBinaryData(habboAssetSWF, "manifest", false);
|
||||
if (binaryData !== null) {
|
||||
return await parser.parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static async getAnimationXML(habboAssetSWF: HabboAssetSWF): Promise<any> {
|
||||
const binaryData: DefineBinaryDataTag | null = this.getBinaryData(habboAssetSWF, "animation", false);
|
||||
if (binaryData !== null) {
|
||||
return await parser.parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async convertXML2JSON(habboAssetSWF: HabboAssetSWF): Promise<EffectJson | null> {
|
||||
const manifestXML = await EffectConverter.getManifestXML(habboAssetSWF);
|
||||
const animationXML = await EffectConverter.getAnimationXML(habboAssetSWF);
|
||||
|
||||
return this._effectJsonMapper.mapXML(habboAssetSWF, manifestXML, animationXML);
|
||||
}
|
||||
|
||||
private async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, archiveType: BundleTypes) {
|
||||
const effectJson = await this.convertXML2JSON(habboAssetSWF);
|
||||
if (effectJson !== null) {
|
||||
effectJson.spritesheet = archiveType.spriteSheetType;
|
||||
effectJson.type = type;
|
||||
|
||||
const path = outputFolder + "/" + habboAssetSWF.getDocumentClass() + ".nitro";
|
||||
const assetOutputFolder = new File(path);
|
||||
if (assetOutputFolder.exists()) {
|
||||
console.log("Effect already exists or the directory is not empty!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const nitroBundle = new NitroBundle();
|
||||
nitroBundle.addFile(habboAssetSWF.getDocumentClass() + ".json", Buffer.from(JSON.stringify(effectJson)));
|
||||
nitroBundle.addFile(archiveType.imageData.name, archiveType.imageData.buffer);
|
||||
|
||||
const buffer = await nitroBundle.toBufferAsync();
|
||||
await fs.writeFile(path, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public async convertAsync() {
|
||||
const outputFolderEffect = new File(this._config.getValue("output.folder.effect"));
|
||||
if (!outputFolderEffect.isDirectory()) {
|
||||
outputFolderEffect.mkdirs();
|
||||
}
|
||||
|
||||
const effectConverter = this;
|
||||
await this._effectDownloader.download(async function (habboAssetSwf: HabboAssetSWF) {
|
||||
console.log("Attempt parsing effect: " + habboAssetSwf.getDocumentClass());
|
||||
|
||||
try {
|
||||
const spriteSheetType = await effectConverter._bundleProvider.generateSpriteSheet(habboAssetSwf, outputFolderEffect.path, "effect");
|
||||
if (spriteSheetType !== null) {
|
||||
await effectConverter.fromHabboAsset(habboAssetSwf, outputFolderEffect.path, "effect", spriteSheetType);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log("Effect error: " + habboAssetSwf.getDocumentClass());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
import Configuration from "../config/Configuration";
|
||||
import HabboAssetSWF from "../swf/HabboAssetSWF";
|
||||
import File from "../utils/File";
|
||||
import {singleton} from "tsyringe";
|
||||
import Logger from "../utils/Logger";
|
||||
|
||||
const fetch = require('node-fetch');
|
||||
const xml2js = require('xml2js');
|
||||
const parser = new xml2js.Parser(/* options */);
|
||||
|
||||
@singleton()
|
||||
export default class EffectDownloader {
|
||||
|
||||
constructor(
|
||||
private readonly _config: Configuration,
|
||||
private readonly _logger: Logger) {
|
||||
}
|
||||
|
||||
public static types: Map<string, string> = new Map<string, string>();
|
||||
|
||||
public async download(callback: (habboAssetSwf: HabboAssetSWF) => Promise<void>) {
|
||||
const outputFolderEffect = this._config.getValue("output.folder.effect");
|
||||
const figureMap = await this.parseEffectMap();
|
||||
const map = figureMap.map;
|
||||
|
||||
for (const lib of map.effect) {
|
||||
const info = lib['$'];
|
||||
const className: string = info.lib;
|
||||
|
||||
const assetOutputFolder = new File(outputFolderEffect + "/" + className);
|
||||
if (assetOutputFolder.exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!EffectDownloader.types.has(className)) {
|
||||
const url = this._config.getValue("dynamic.download.url.effect").replace("%className%", className);
|
||||
let buffer: Buffer | null = null;
|
||||
|
||||
if (url.includes("http")) {
|
||||
const fetchData = await fetch(url);
|
||||
if (fetchData.status === 404) {
|
||||
console.log("SWF File does not exist: " + url);
|
||||
continue;
|
||||
}
|
||||
|
||||
const arrayBuffer = await fetchData.arrayBuffer();
|
||||
buffer = Buffer.from(arrayBuffer);
|
||||
} else {
|
||||
const file = new File(url);
|
||||
if (!file.exists()) {
|
||||
console.log("SWF File does not exist: " + file.path);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const newHabboAssetSWF: HabboAssetSWF = new HabboAssetSWF(buffer !== null ? buffer : url);
|
||||
await newHabboAssetSWF.setupAsync();
|
||||
|
||||
EffectDownloader.types.set(className, info.type);
|
||||
await callback(newHabboAssetSWF);
|
||||
} catch (e) {
|
||||
await this._logger.logErrorAsync(`[${className}]` + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async parseEffectMap() {
|
||||
const figureMapPath = this._config.getValue("effectmap.url");
|
||||
const figureFetch = await fetch(figureMapPath);
|
||||
const figureMap = await figureFetch.text();
|
||||
|
||||
return await parser.parseStringPromise(figureMap);
|
||||
}
|
||||
}
|
@ -1,522 +0,0 @@
|
||||
export class AnimationXML {
|
||||
private readonly _name: string;
|
||||
private readonly _desc: string;
|
||||
private readonly _resetOnToggle: boolean | undefined;
|
||||
|
||||
private readonly _directions: Array<DirectionOffsetXML>;
|
||||
private readonly _shadows: Array<ShadowXML>;
|
||||
private readonly _adds: Array<AddXML>;
|
||||
private readonly _removes: Array<RemoveXML>;
|
||||
private readonly _sprites: Array<SpriteXML>;
|
||||
private readonly _frames: Array<FrameXML>;
|
||||
private readonly _avatars: Array<AvatarXML>;
|
||||
private readonly _overrides: Array<OverrideXML>;
|
||||
|
||||
constructor(animationXML: any) {
|
||||
const animation = animationXML.animation;
|
||||
const attributes = animation.$;
|
||||
|
||||
this._name = attributes.name;
|
||||
this._desc = attributes.desc;
|
||||
|
||||
if (attributes.resetOnToggle !== undefined) this._resetOnToggle = attributes.resetOnToggle === '1';
|
||||
|
||||
this._directions = new Array<DirectionOffsetXML>();
|
||||
if (animation.direction !== undefined) {
|
||||
for (const direction of animation.direction) {
|
||||
this._directions.push(new DirectionOffsetXML(direction));
|
||||
}
|
||||
}
|
||||
|
||||
this._shadows = new Array<ShadowXML>();
|
||||
if (animation.shadow !== undefined) {
|
||||
for (const shadow of animation.shadow) {
|
||||
this._shadows.push(new ShadowXML(shadow));
|
||||
}
|
||||
}
|
||||
|
||||
this._adds = new Array<AddXML>();
|
||||
if (animation.add !== undefined) {
|
||||
for (const add of animation.add) {
|
||||
this._adds.push(new AddXML(add));
|
||||
}
|
||||
}
|
||||
|
||||
this._removes = new Array<RemoveXML>();
|
||||
if (animation.remove !== undefined) {
|
||||
for (const remove of animation.remove) {
|
||||
this._removes.push(new RemoveXML(remove));
|
||||
}
|
||||
}
|
||||
|
||||
this._sprites = new Array<SpriteXML>();
|
||||
if (animation.sprite !== undefined) {
|
||||
for (const sprite of animation.sprite) {
|
||||
this._sprites.push(new SpriteXML(sprite));
|
||||
}
|
||||
}
|
||||
|
||||
this._frames = new Array<FrameXML>();
|
||||
if (animation.frame !== undefined) {
|
||||
for (const frame of animation.frame) {
|
||||
this._frames.push(new FrameXML(frame));
|
||||
}
|
||||
}
|
||||
|
||||
this._avatars = new Array<AvatarXML>();
|
||||
if (animation.avatar !== undefined) {
|
||||
for (const avatar of animation.avatar) {
|
||||
this._avatars.push(new AvatarXML(avatar));
|
||||
}
|
||||
}
|
||||
|
||||
this._overrides = new Array<OverrideXML>();
|
||||
if (animation.override !== undefined) {
|
||||
for (const override of animation.override) {
|
||||
this._overrides.push(new OverrideXML(override));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get desc(): string {
|
||||
return this._desc;
|
||||
}
|
||||
|
||||
get resetOnToggle(): boolean | undefined {
|
||||
return this._resetOnToggle;
|
||||
}
|
||||
|
||||
get directions(): Array<DirectionOffsetXML> {
|
||||
return this._directions;
|
||||
}
|
||||
|
||||
get shadows(): Array<ShadowXML> {
|
||||
return this._shadows;
|
||||
}
|
||||
|
||||
get adds(): Array<AddXML> {
|
||||
return this._adds;
|
||||
}
|
||||
|
||||
get removes(): Array<RemoveXML> {
|
||||
return this._removes;
|
||||
}
|
||||
|
||||
get sprites(): Array<SpriteXML> {
|
||||
return this._sprites;
|
||||
}
|
||||
|
||||
get frames(): Array<FrameXML> {
|
||||
return this._frames;
|
||||
}
|
||||
|
||||
get avatars(): Array<AvatarXML> {
|
||||
return this._avatars;
|
||||
}
|
||||
|
||||
get overrides(): Array<OverrideXML> {
|
||||
return this._overrides;
|
||||
}
|
||||
}
|
||||
|
||||
export class OverrideXML {
|
||||
private readonly _name: string;
|
||||
private readonly _override: string;
|
||||
|
||||
private readonly _frames: Array<FrameXML>;
|
||||
|
||||
constructor(overrideXML: any) {
|
||||
const attributes = overrideXML.$;
|
||||
|
||||
this._name = attributes.name;
|
||||
this._override = attributes.override;
|
||||
|
||||
this._frames = new Array<FrameXML>();
|
||||
if (overrideXML.frame !== undefined) {
|
||||
for (const frame of overrideXML.frame) {
|
||||
this._frames.push(new FrameXML(frame));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get override(): string {
|
||||
return this._override;
|
||||
}
|
||||
|
||||
get frames(): Array<FrameXML> {
|
||||
return this._frames;
|
||||
}
|
||||
}
|
||||
|
||||
export class AvatarXML {
|
||||
private readonly _ink: number;
|
||||
private readonly _foreground: string;
|
||||
private readonly _background: string;
|
||||
|
||||
constructor(avatarXML: any) {
|
||||
const attributes = avatarXML.$;
|
||||
|
||||
this._ink = attributes.ink;
|
||||
this._foreground = attributes.foreground;
|
||||
this._background = attributes.background;
|
||||
}
|
||||
|
||||
get ink(): number {
|
||||
return this._ink;
|
||||
}
|
||||
|
||||
get foreground(): string {
|
||||
return this._foreground;
|
||||
}
|
||||
|
||||
get background(): string {
|
||||
return this._background;
|
||||
}
|
||||
}
|
||||
|
||||
export class SpriteXML {
|
||||
private readonly _id: string;
|
||||
private readonly _member: string;
|
||||
private readonly _directions: number;
|
||||
private readonly _staticY: number;
|
||||
private readonly _ink: number;
|
||||
|
||||
private readonly _directionList: Array<DirectionXML>;
|
||||
|
||||
constructor(spriteXML: any) {
|
||||
const attributes = spriteXML.$;
|
||||
|
||||
this._id = attributes.id;
|
||||
this._member = attributes.member;
|
||||
this._directions = attributes.directions;
|
||||
this._staticY = attributes.staticY;
|
||||
this._ink = attributes.ink;
|
||||
|
||||
this._directionList = new Array<DirectionXML>();
|
||||
if (spriteXML.direction !== undefined) {
|
||||
for (const direction of spriteXML.direction) {
|
||||
this._directionList.push(new DirectionXML(direction));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get member(): string {
|
||||
return this._member;
|
||||
}
|
||||
|
||||
get directions(): number {
|
||||
return this._directions;
|
||||
}
|
||||
|
||||
get staticY(): number {
|
||||
return this._staticY;
|
||||
}
|
||||
|
||||
get ink(): number {
|
||||
return this._ink;
|
||||
}
|
||||
|
||||
get directionList(): Array<DirectionXML> {
|
||||
return this._directionList;
|
||||
}
|
||||
}
|
||||
|
||||
export class DirectionXML {
|
||||
private readonly _id: number;
|
||||
private readonly _dx: number;
|
||||
private readonly _dy: number;
|
||||
private readonly _dz: number;
|
||||
|
||||
constructor(directionXML: any) {
|
||||
const attributes = directionXML.$;
|
||||
|
||||
this._id = attributes.id;
|
||||
this._dx = attributes.dx;
|
||||
this._dy = attributes.dy;
|
||||
this._dz = attributes.dz;
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get dx(): number {
|
||||
return this._dx;
|
||||
}
|
||||
|
||||
get dy(): number {
|
||||
return this._dy;
|
||||
}
|
||||
|
||||
get dz(): number {
|
||||
return this._dz;
|
||||
}
|
||||
}
|
||||
|
||||
export class RemoveXML {
|
||||
private readonly _id: string;
|
||||
|
||||
constructor(removeXML: any) {
|
||||
this._id = removeXML.$.id;
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this._id;
|
||||
}
|
||||
}
|
||||
|
||||
export class AddXML {
|
||||
private readonly _id: string;
|
||||
private readonly _align: string;
|
||||
private readonly _blend: string;
|
||||
private readonly _ink: number;
|
||||
private readonly _base: string;
|
||||
|
||||
constructor(addXML: any) {
|
||||
const attributes = addXML.$;
|
||||
|
||||
this._id = attributes.id;
|
||||
this._align = attributes.align;
|
||||
this._blend = attributes.blend;
|
||||
this._ink = attributes.ink;
|
||||
this._base = attributes.base;
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get align(): string {
|
||||
return this._align;
|
||||
}
|
||||
|
||||
get blend(): string {
|
||||
return this._blend;
|
||||
}
|
||||
|
||||
get ink(): number {
|
||||
return this._ink;
|
||||
}
|
||||
|
||||
get base(): string {
|
||||
return this._base;
|
||||
}
|
||||
}
|
||||
|
||||
export class FrameXML {
|
||||
private readonly _repeats: number | undefined;
|
||||
private readonly _fxs: Array<FxXML>;
|
||||
private readonly _bodyParts: Array<BodyPartXML>;
|
||||
|
||||
constructor(frameXML: any) {
|
||||
if (frameXML.$ !== undefined)
|
||||
this._repeats = frameXML.$.repeats;
|
||||
|
||||
this._fxs = new Array<FxXML>();
|
||||
if (frameXML.fx !== undefined) {
|
||||
for (const fx of frameXML.fx) {
|
||||
this._fxs.push(new FxXML(fx));
|
||||
}
|
||||
}
|
||||
|
||||
this._bodyParts = new Array<BodyPartXML>();
|
||||
if (frameXML.bodypart !== undefined) {
|
||||
for (const bodypart of frameXML.bodypart) {
|
||||
this._bodyParts.push(new BodyPartXML(bodypart));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get repeats(): number | undefined {
|
||||
return this._repeats;
|
||||
}
|
||||
|
||||
get fxs(): Array<FxXML> {
|
||||
return this._fxs;
|
||||
}
|
||||
|
||||
get bodyParts(): Array<BodyPartXML> {
|
||||
return this._bodyParts;
|
||||
}
|
||||
}
|
||||
|
||||
export class BodyPartXML {
|
||||
private readonly _id: string;
|
||||
private readonly _frame: number;
|
||||
private readonly _dx: number;
|
||||
private readonly _dy: number;
|
||||
private readonly _dz: number;
|
||||
private readonly _dd: number;
|
||||
private readonly _action: string;
|
||||
private readonly _base: string;
|
||||
|
||||
private readonly _items: Array<ItemXML>;
|
||||
|
||||
constructor(bodyPartXML: any) {
|
||||
const attributes = bodyPartXML.$;
|
||||
|
||||
this._id = attributes.id;
|
||||
this._frame = attributes.frame;
|
||||
this._dx = attributes.dx;
|
||||
this._dy = attributes.dy;
|
||||
this._dz = attributes.dz;
|
||||
this._dd = attributes.dd;
|
||||
this._action = attributes.action;
|
||||
this._base = attributes.base;
|
||||
|
||||
this._items = new Array<ItemXML>();
|
||||
if (bodyPartXML.item !== undefined) {
|
||||
for (const item of bodyPartXML.item) {
|
||||
this._items.push(new ItemXML(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get frame(): number {
|
||||
return this._frame;
|
||||
}
|
||||
|
||||
get dx(): number {
|
||||
return this._dx;
|
||||
}
|
||||
|
||||
get dy(): number {
|
||||
return this._dy;
|
||||
}
|
||||
|
||||
get dz(): number {
|
||||
return this._dz;
|
||||
}
|
||||
|
||||
get dd(): number {
|
||||
return this._dd;
|
||||
}
|
||||
|
||||
get action(): string {
|
||||
return this._action;
|
||||
}
|
||||
|
||||
get base(): string {
|
||||
return this._base;
|
||||
}
|
||||
|
||||
get items(): Array<ItemXML> {
|
||||
return this._items;
|
||||
}
|
||||
}
|
||||
|
||||
export class ItemXML {
|
||||
private readonly _id: string;
|
||||
private readonly _base: string;
|
||||
|
||||
constructor(itemXML: any) {
|
||||
const attributes = itemXML.$;
|
||||
|
||||
this._id = attributes.id;
|
||||
this._base = attributes.base;
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get base(): string {
|
||||
return this._base;
|
||||
}
|
||||
}
|
||||
|
||||
export class FxXML {
|
||||
private readonly _id: string;
|
||||
private readonly _repeats: number;
|
||||
private readonly _frame: number;
|
||||
private readonly _dx: number;
|
||||
private readonly _dy: number;
|
||||
private readonly _dz: number;
|
||||
private readonly _dd: number;
|
||||
private readonly _action: string;
|
||||
|
||||
constructor(fxXML: any) {
|
||||
const attributes = fxXML.$;
|
||||
|
||||
this._id = attributes.id;
|
||||
this._repeats = attributes.repeats;
|
||||
this._frame = attributes.frame;
|
||||
this._dx = attributes.dx;
|
||||
this._dy = attributes.dy;
|
||||
this._dz = attributes.dz;
|
||||
this._dd = attributes.dd;
|
||||
this._action = attributes.action;
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get repeats(): number {
|
||||
return this._repeats;
|
||||
}
|
||||
|
||||
get frame(): number {
|
||||
return this._frame;
|
||||
}
|
||||
|
||||
get dx(): number {
|
||||
return this._dx;
|
||||
}
|
||||
|
||||
get dy(): number {
|
||||
return this._dy;
|
||||
}
|
||||
|
||||
get dz(): number {
|
||||
return this._dz;
|
||||
}
|
||||
|
||||
get dd(): number {
|
||||
return this._dd;
|
||||
}
|
||||
|
||||
get action(): string {
|
||||
return this._action;
|
||||
}
|
||||
}
|
||||
|
||||
export class ShadowXML {
|
||||
private readonly _id: string;
|
||||
|
||||
constructor(shadowXML: any) {
|
||||
this._id = shadowXML.$.id;
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this._id;
|
||||
}
|
||||
}
|
||||
|
||||
export class DirectionOffsetXML {
|
||||
private readonly _offset: number;
|
||||
|
||||
constructor(directionXML: any) {
|
||||
this._offset = directionXML.$.offset;
|
||||
}
|
||||
|
||||
get offset(): number {
|
||||
return this._offset;
|
||||
}
|
||||
}
|
@ -1,341 +0,0 @@
|
||||
import HabboAssetSWF from "../../swf/HabboAssetSWF";
|
||||
import {
|
||||
Add,
|
||||
Alias,
|
||||
Aliases,
|
||||
Animation,
|
||||
Animations,
|
||||
AssetJSON,
|
||||
AssetsJSON, Avatar,
|
||||
Bodypart, Direction, DirectionOffset,
|
||||
EffectJson,
|
||||
Frame,
|
||||
Fx, Item, Override, Remove, Shadow, Sprite
|
||||
} from "./EffectTypes";
|
||||
import {ManifestXML} from "./EffectManifestXMLTypes";
|
||||
import {
|
||||
AnimationXML,
|
||||
BodyPartXML
|
||||
} from "./EffectAnimationXMLTypes";
|
||||
import {singleton} from "tsyringe";
|
||||
import EffectDownloader from "../EffectDownloader";
|
||||
import BundleProvider from "../../bundle/BundleProvider";
|
||||
|
||||
@singleton()
|
||||
export default class EffectJsonMapper {
|
||||
public static readonly MUST_START_WITH: string = "h_";
|
||||
|
||||
|
||||
public mapXML(habboAssetSWF: HabboAssetSWF, manifest: any, animation: any): EffectJson {
|
||||
const name = habboAssetSWF.getDocumentClass();
|
||||
const result = {} as EffectJson;
|
||||
result.name = name;
|
||||
result.type = EffectDownloader.types.get(name) as string;
|
||||
this.mapManifestXML(new ManifestXML(manifest), result);
|
||||
EffectJsonMapper.mapAnimationXML(new AnimationXML(animation), result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private mapManifestXML(manifestXML: ManifestXML, output: EffectJson) {
|
||||
const assets: AssetsJSON = {};
|
||||
|
||||
for (const assetXML of manifestXML.library.assets) {
|
||||
if (assetXML.name.startsWith(EffectJsonMapper.MUST_START_WITH)) {
|
||||
|
||||
const asset: AssetJSON = {} as any;
|
||||
if (assetXML.param != undefined && assetXML.param.value !== undefined) {
|
||||
asset.x = parseInt(assetXML.param.value.split(",")[0]);
|
||||
asset.y = parseInt(assetXML.param.value.split(",")[1]);
|
||||
}
|
||||
if (BundleProvider.imageSource.has(assetXML.name)) {
|
||||
asset.source = BundleProvider.imageSource.get(assetXML.name) as string;
|
||||
}
|
||||
|
||||
assets[assetXML.name] = asset;
|
||||
}
|
||||
}
|
||||
|
||||
output.assets = assets;
|
||||
|
||||
if (manifestXML.library.aliases.length > 0 || BundleProvider.imageSource.size > 0) {
|
||||
const aliases: Aliases = {};
|
||||
for (const aliasXML of manifestXML.library.aliases) {
|
||||
if (aliasXML.name.startsWith(EffectJsonMapper.MUST_START_WITH)) {
|
||||
const alias: Alias = {} as any;
|
||||
|
||||
alias.link = aliasXML.link;
|
||||
if (aliasXML.fliph !== undefined)
|
||||
alias.fliph = parseInt(aliasXML.fliph.toString());
|
||||
if (aliasXML.flipv !== undefined)
|
||||
alias.flipv = parseInt(aliasXML.flipv.toString());
|
||||
|
||||
aliases[aliasXML.name] = alias;
|
||||
}
|
||||
}
|
||||
|
||||
output.aliases = aliases;
|
||||
}
|
||||
}
|
||||
|
||||
private static mapAnimationXML(animationXML: AnimationXML, output: EffectJson) {
|
||||
const animations: Animations = {};
|
||||
const animation: Animation = {} as any;
|
||||
animation.name = animationXML.name;
|
||||
animation.desc = animationXML.desc;
|
||||
animation.resetOnToggle = animationXML.resetOnToggle as any;
|
||||
|
||||
const frames: Array<Frame> = new Array<Frame>();
|
||||
const avatars: Array<Avatar> = new Array<Avatar>();
|
||||
const directions: Array<DirectionOffset> = new Array<DirectionOffset>();
|
||||
const shadows: Array<Shadow> = new Array<Shadow>();
|
||||
const adds: Array<Add> = new Array<Add>();
|
||||
const removes: Array<Remove> = new Array<Remove>();
|
||||
const sprites: Array<Sprite> = new Array<Sprite>();
|
||||
const overrides: Array<Override> = new Array<Override>();
|
||||
if (animationXML.frames.length > 0) {
|
||||
for (const frameXML of animationXML.frames) {
|
||||
const fxs: Array<Fx> = new Array<Fx>();
|
||||
const bodyparts: Array<Bodypart> = new Array<BodyPartXML>();
|
||||
|
||||
const frame: Frame = {} as any;
|
||||
if (frameXML.fxs.length > 0) {
|
||||
for (const fxXML of frameXML.fxs) {
|
||||
const fx: Fx = {} as any;
|
||||
fx.action = fxXML.action;
|
||||
|
||||
if (fxXML.dx !== undefined)
|
||||
fx.dx = parseInt(fxXML.dx.toString());
|
||||
|
||||
if (fxXML.dy !== undefined)
|
||||
fx.dy = parseInt(fxXML.dy.toString());
|
||||
|
||||
if (fxXML.dz !== undefined)
|
||||
fx.dz = parseInt(fxXML.dz.toString());
|
||||
|
||||
if (fxXML.dd !== undefined)
|
||||
fx.dd = parseInt(fxXML.dd.toString());
|
||||
|
||||
if (fxXML.frame !== undefined)
|
||||
fx.frame = parseInt(fxXML.frame.toString());
|
||||
fx.id = fxXML.id;
|
||||
|
||||
fxs.push(fx);
|
||||
}
|
||||
}
|
||||
if (frameXML.bodyParts.length > 0) {
|
||||
for (const bodypartXML of frameXML.bodyParts) {
|
||||
const items: Array<Item> = new Array<Item>();
|
||||
const bodypart: Bodypart = {} as any;
|
||||
if (bodypartXML.items.length > 0) {
|
||||
for (const itemXML of bodypartXML.items) {
|
||||
const item: Item = {} as any;
|
||||
item.id = itemXML.id;
|
||||
item.base = itemXML.base;
|
||||
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
bodypart.action = bodypartXML.action;
|
||||
|
||||
if (bodypartXML.dx !== undefined)
|
||||
bodypart.dx = parseInt(bodypartXML.dx.toString());
|
||||
|
||||
if (bodypartXML.dy !== undefined)
|
||||
bodypart.dy = parseInt(bodypartXML.dy.toString());
|
||||
|
||||
if (bodypartXML.dz !== undefined)
|
||||
bodypart.dz = parseInt(bodypartXML.dz.toString());
|
||||
|
||||
if (bodypartXML.dd !== undefined)
|
||||
bodypart.dd = parseInt(bodypartXML.dd.toString());
|
||||
|
||||
if (bodypartXML.frame !== undefined)
|
||||
bodypart.frame = parseInt(bodypartXML.frame.toString());
|
||||
bodypart.id = bodypartXML.id;
|
||||
bodypart.base = bodypartXML.base;
|
||||
bodypart.items = items;
|
||||
|
||||
bodyparts.push(bodypart);
|
||||
}
|
||||
}
|
||||
if (frameXML.repeats !== undefined) frame.repeats = parseInt(frameXML.repeats.toString());
|
||||
frame.fxs = fxs;
|
||||
frame.bodyparts = bodyparts;
|
||||
frames.push(frame);
|
||||
}
|
||||
}
|
||||
if (animationXML.avatars.length > 0) {
|
||||
for (const avatarXML of animationXML.avatars) {
|
||||
const avatar: Avatar = {} as any;
|
||||
avatar.background = avatarXML.background;
|
||||
avatar.foreground = avatarXML.foreground;
|
||||
|
||||
if (avatarXML.ink !== undefined)
|
||||
avatar.ink = parseInt(avatarXML.ink.toString());
|
||||
|
||||
avatars.push(avatar);
|
||||
}
|
||||
}
|
||||
if (animationXML.directions.length > 0) {
|
||||
for (const directionXML of animationXML.directions) {
|
||||
const direction: DirectionOffset = {} as any;
|
||||
direction.offset = parseInt(directionXML.offset.toString());
|
||||
|
||||
directions.push(direction);
|
||||
}
|
||||
}
|
||||
if (animationXML.shadows.length > 0) {
|
||||
for (const shadowXML of animationXML.shadows) {
|
||||
const shadow: Shadow = {} as any;
|
||||
shadow.id = shadowXML.id;
|
||||
|
||||
shadows.push(shadow);
|
||||
}
|
||||
}
|
||||
if (animationXML.adds.length > 0) {
|
||||
for (const addXML of animationXML.adds) {
|
||||
const add: Add = {} as any;
|
||||
add.id = addXML.id;
|
||||
add.align = addXML.align;
|
||||
add.blend = addXML.blend;
|
||||
|
||||
if (addXML.ink !== undefined)
|
||||
add.ink = parseInt(addXML.ink.toString());
|
||||
add.base = addXML.base;
|
||||
|
||||
adds.push(add);
|
||||
}
|
||||
}
|
||||
if (animationXML.removes.length > 0) {
|
||||
for (const removeXML of animationXML.removes) {
|
||||
const remove: Remove = {} as any;
|
||||
remove.id = removeXML.id;
|
||||
|
||||
removes.push(remove);
|
||||
}
|
||||
}
|
||||
if (animationXML.sprites.length > 0) {
|
||||
for (const spriteXML of animationXML.sprites) {
|
||||
const sprite: Sprite = {} as any;
|
||||
const directions2: Array<Direction> = new Array<Direction>();
|
||||
if (spriteXML.directionList.length > 0) {
|
||||
for (const directionXML of spriteXML.directionList) {
|
||||
const direction: Direction = {} as any;
|
||||
direction.id = parseInt(directionXML.id.toString());
|
||||
|
||||
if (directionXML.dx !== undefined)
|
||||
direction.dx = parseInt(directionXML.dx.toString());
|
||||
|
||||
if (directionXML.dy !== undefined)
|
||||
direction.dy = parseInt(directionXML.dy.toString());
|
||||
|
||||
if (directionXML.dz !== undefined)
|
||||
direction.dz = parseInt(directionXML.dz.toString());
|
||||
|
||||
directions2.push(direction);
|
||||
}
|
||||
}
|
||||
sprite.directionList = directions2;
|
||||
|
||||
if (spriteXML.directions !== undefined)
|
||||
sprite.directions = parseInt(spriteXML.directions.toString());
|
||||
sprite.id = spriteXML.id;
|
||||
|
||||
if (spriteXML.ink !== undefined)
|
||||
sprite.ink = parseInt(spriteXML.ink.toString());
|
||||
|
||||
if (spriteXML.member !== undefined)
|
||||
sprite.member = spriteXML.member;
|
||||
|
||||
if (spriteXML.staticY !== undefined)
|
||||
sprite.staticY = parseInt(spriteXML.staticY.toString());
|
||||
sprites.push(sprite);
|
||||
}
|
||||
}
|
||||
if (animationXML.overrides.length > 0) {
|
||||
for (const overrideXML of animationXML.overrides) {
|
||||
const override: Override = {} as any;
|
||||
override.name = overrideXML.name;
|
||||
override.override = overrideXML.override;
|
||||
if (overrideXML.frames.length > 0) {
|
||||
const overrideFrames: Array<Frame> = new Array<Frame>();
|
||||
for (const frameXML of overrideXML.frames) {
|
||||
const fxs: Array<Fx> = new Array<Fx>();
|
||||
const bodyparts: Array<Bodypart> = new Array<Bodypart>();
|
||||
const frame: Frame = {} as any;
|
||||
if (frameXML.fxs.length > 0) {
|
||||
for (const fxXML of frameXML.fxs) {
|
||||
const fx: Fx = {} as any;
|
||||
fx.action = fxXML.action;
|
||||
if (fxXML.dx !== undefined)
|
||||
fx.dx = parseInt(fxXML.dx.toString());
|
||||
if (fxXML.dy !== undefined)
|
||||
fx.dy = parseInt(fxXML.dy.toString());
|
||||
if (fxXML.dz !== undefined)
|
||||
fx.dz = parseInt(fxXML.dz.toString());
|
||||
if (fxXML.dd !== undefined)
|
||||
fx.dd = parseInt(fxXML.dd.toString());
|
||||
|
||||
if (fxXML.frame !== undefined)
|
||||
fx.frame = parseInt(fxXML.frame.toString());
|
||||
fx.id = fxXML.id;
|
||||
|
||||
fxs.push(fx);
|
||||
}
|
||||
}
|
||||
if (frameXML.bodyParts.length > 0) {
|
||||
for (const bodypartXML of frameXML.bodyParts) {
|
||||
const items: Array<Item> = new Array<Item>();
|
||||
const bodypart: Bodypart = {} as any;
|
||||
if (bodypartXML.items.length > 0) {
|
||||
for (const itemXML of bodypartXML.items) {
|
||||
const item: Item = {} as any;
|
||||
item.id = itemXML.id;
|
||||
item.base = itemXML.base;
|
||||
|
||||
items.push(item);
|
||||
}
|
||||
}
|
||||
bodypart.action = bodypartXML.action;
|
||||
|
||||
if (bodypartXML.dx !== undefined)
|
||||
bodypart.dx = parseInt(bodypartXML.dx.toString());
|
||||
if (bodypartXML.dy !== undefined)
|
||||
bodypart.dy = parseInt(bodypartXML.dy.toString());
|
||||
if (bodypartXML.dz !== undefined)
|
||||
bodypart.dz = parseInt(bodypartXML.dz.toString());
|
||||
if (bodypartXML.dd !== undefined)
|
||||
bodypart.dd = parseInt(bodypartXML.dd.toString());
|
||||
|
||||
if (bodypartXML.frame !== undefined)
|
||||
bodypart.frame = parseInt(bodypartXML.frame.toString());
|
||||
bodypart.id = bodypartXML.id;
|
||||
bodypart.base = bodypartXML.base;
|
||||
bodypart.items = items;
|
||||
|
||||
bodyparts.push(bodypart);
|
||||
}
|
||||
}
|
||||
frame.fxs = fxs;
|
||||
frame.bodyparts = bodyparts;
|
||||
overrideFrames.push(frame);
|
||||
}
|
||||
override.frames = overrideFrames;
|
||||
overrides.push(override);
|
||||
}
|
||||
}
|
||||
}
|
||||
animation.frames = frames;
|
||||
animation.shadows = shadows;
|
||||
animation.adds = adds;
|
||||
animation.directions = directions;
|
||||
animation.avatars = avatars;
|
||||
animation.removes = removes;
|
||||
animation.sprites = sprites;
|
||||
animation.overrides = overrides;
|
||||
animations[output.name] = animation;
|
||||
|
||||
output.animations = animations;
|
||||
}
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
export class ManifestXML {
|
||||
private readonly _library: LibraryXML;
|
||||
|
||||
constructor(manifestXML: any) {
|
||||
this._library = new LibraryXML(manifestXML.manifest.library[0]);
|
||||
}
|
||||
|
||||
get library(): LibraryXML {
|
||||
return this._library;
|
||||
}
|
||||
}
|
||||
|
||||
export class LibraryXML {
|
||||
private readonly _name: string;
|
||||
private readonly _version: string;
|
||||
|
||||
private readonly _assets: Array<AssetXML>;
|
||||
private readonly _aliases: Array<AliasXML>;
|
||||
|
||||
constructor(libraryXML: any) {
|
||||
const attributes = libraryXML.$;
|
||||
this._name = attributes.id;
|
||||
this._version = attributes.version;
|
||||
|
||||
this._assets = new Array<AssetXML>();
|
||||
if (libraryXML.assets !== undefined) {
|
||||
for (const assetParent of libraryXML.assets) {
|
||||
for (const asset of assetParent.asset) {
|
||||
this._assets.push(new AssetXML(asset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._aliases = new Array<AliasXML>();
|
||||
if (libraryXML.aliases !== undefined && Array.isArray(libraryXML.aliases)) {
|
||||
for (const aliasParent of libraryXML.aliases) {
|
||||
if (Array.isArray(aliasParent.alias)) {
|
||||
for (const alias of aliasParent.alias) {
|
||||
this._aliases.push(new AliasXML(alias));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get version(): string {
|
||||
return this._version;
|
||||
}
|
||||
|
||||
get assets(): Array<AssetXML> {
|
||||
return this._assets;
|
||||
}
|
||||
|
||||
get aliases(): Array<AliasXML> {
|
||||
return this._aliases;
|
||||
}
|
||||
}
|
||||
|
||||
export class AliasXML {
|
||||
private readonly _name: string;
|
||||
private readonly _link: string;
|
||||
private readonly _fliph: number;
|
||||
private readonly _flipv: number;
|
||||
|
||||
constructor(aliasXML: any) {
|
||||
const attributes = aliasXML.$;
|
||||
|
||||
this._name = attributes.name;
|
||||
this._link = attributes.link;
|
||||
this._fliph = attributes.fliph;
|
||||
this._flipv = attributes.flipv;
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get link(): string {
|
||||
return this._link;
|
||||
}
|
||||
|
||||
get fliph(): number {
|
||||
return this._fliph;
|
||||
}
|
||||
|
||||
get flipv(): number {
|
||||
return this._flipv;
|
||||
}
|
||||
}
|
||||
|
||||
export class AssetXML {
|
||||
private readonly _name: string;
|
||||
private readonly _mimeType: string;
|
||||
private readonly _param: ParamXML | undefined;
|
||||
|
||||
constructor(assetXML: any) {
|
||||
const attributes = assetXML.$;
|
||||
this._name = attributes.name;
|
||||
this._mimeType = attributes.mimeType;
|
||||
|
||||
if (assetXML.param !== undefined) {
|
||||
for (const param of assetXML.param) {
|
||||
this._param = new ParamXML(param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get mimeType(): string {
|
||||
return this._mimeType;
|
||||
}
|
||||
|
||||
get param(): ParamXML | undefined {
|
||||
return this._param;
|
||||
}
|
||||
}
|
||||
|
||||
export class ParamXML {
|
||||
private readonly _key: string;
|
||||
private readonly _value: string;
|
||||
|
||||
constructor(paramXML: any) {
|
||||
const attributes = paramXML.$;
|
||||
this._key = attributes.key;
|
||||
this._value = attributes.value;
|
||||
}
|
||||
|
||||
get key(): string {
|
||||
return this._key;
|
||||
}
|
||||
|
||||
get value(): string {
|
||||
return this._value;
|
||||
}
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
import {SpriteSheetType} from "../../bundle/BundleTypes";
|
||||
|
||||
export interface EffectJson {
|
||||
type: string,
|
||||
name: string,
|
||||
spritesheet: SpriteSheetType,
|
||||
|
||||
assets: AssetsJSON,
|
||||
aliases: Aliases,
|
||||
animations: Animations
|
||||
}
|
||||
|
||||
export interface Animations {
|
||||
[key: string]: Animation
|
||||
}
|
||||
|
||||
export interface Animation {
|
||||
name: string,
|
||||
desc: string,
|
||||
resetOnToggle: boolean,
|
||||
|
||||
directions: Array<DirectionOffset>,
|
||||
shadows: Array<Shadow>,
|
||||
adds: Array<Add>,
|
||||
removes: Array<Remove>,
|
||||
sprites: Array<Sprite>,
|
||||
frames: Array<Frame>,
|
||||
avatars: Array<Avatar>,
|
||||
overrides: Array<Override>
|
||||
}
|
||||
|
||||
export interface Override {
|
||||
name: string,
|
||||
override: string,
|
||||
|
||||
frames: Array<Frame>;
|
||||
}
|
||||
|
||||
export interface Avatar {
|
||||
ink: number,
|
||||
foreground: string,
|
||||
background: string
|
||||
}
|
||||
|
||||
export interface Frame {
|
||||
repeats: number,
|
||||
|
||||
fxs: Array<Fx>,
|
||||
bodyparts: Array<Bodypart>
|
||||
}
|
||||
|
||||
export interface Bodypart {
|
||||
id: string,
|
||||
frame: number,
|
||||
dx: number,
|
||||
dy: number,
|
||||
dz: number,
|
||||
dd: number,
|
||||
action: string,
|
||||
base: string,
|
||||
|
||||
items: Array<Item>
|
||||
}
|
||||
|
||||
export interface Item {
|
||||
id: string,
|
||||
base: string
|
||||
}
|
||||
|
||||
export interface Fx {
|
||||
id: string,
|
||||
frame: number,
|
||||
dx: number,
|
||||
dy: number,
|
||||
dz: number,
|
||||
dd: number,
|
||||
action: string
|
||||
}
|
||||
|
||||
export interface Sprite {
|
||||
id: string,
|
||||
member: string,
|
||||
directions: number,
|
||||
staticY: number,
|
||||
ink: number,
|
||||
|
||||
directionList: Array<Direction>;
|
||||
}
|
||||
|
||||
export interface Direction {
|
||||
id: number,
|
||||
dx: number,
|
||||
dy: number,
|
||||
dz: number,
|
||||
}
|
||||
|
||||
export interface Remove {
|
||||
id: string
|
||||
}
|
||||
|
||||
export interface Add {
|
||||
id: string,
|
||||
align: string,
|
||||
blend: string,
|
||||
ink: number,
|
||||
base: string
|
||||
}
|
||||
|
||||
export interface Shadow {
|
||||
id: string
|
||||
}
|
||||
|
||||
export interface DirectionOffset {
|
||||
offset: number
|
||||
}
|
||||
|
||||
export interface Aliases {
|
||||
[key: string]: Alias
|
||||
}
|
||||
|
||||
export interface Alias {
|
||||
link: string,
|
||||
fliph: number,
|
||||
flipv: number
|
||||
}
|
||||
|
||||
export interface AssetsJSON {
|
||||
[key: string]: AssetJSON;
|
||||
}
|
||||
|
||||
export interface AssetJSON {
|
||||
source: string,
|
||||
x: number,
|
||||
y: number,
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
import {singleton} from "tsyringe";
|
||||
import HabboAssetSWF from "../swf/HabboAssetSWF";
|
||||
import FigureJsonMapper from "./mapper/FigureJsonMapper";
|
||||
import Configuration from "../config/Configuration";
|
||||
import {FigureJson} from "./mapper/FigureJsonType";
|
||||
import DefineBinaryDataTag from "../swf/tags/DefineBinaryDataTag";
|
||||
import BundleTypes from "../bundle/BundleTypes";
|
||||
import File from "../utils/File";
|
||||
import NitroBundle from "../utils/NitroBundle";
|
||||
import BundleProvider from "../bundle/BundleProvider";
|
||||
import FigureDownloader from "./FigureDownloader";
|
||||
import Logger from "../utils/Logger";
|
||||
|
||||
const xml2js = require('xml2js');
|
||||
const parser = new xml2js.Parser(/* options */);
|
||||
const fs = require('fs').promises;
|
||||
|
||||
@singleton()
|
||||
export default class FigureConverter {
|
||||
|
||||
constructor(
|
||||
private readonly _figureDownloader: FigureDownloader,
|
||||
private readonly _figureJsonMapper: FigureJsonMapper,
|
||||
private readonly _config: Configuration,
|
||||
private readonly _bundleProvider: BundleProvider,
|
||||
private readonly _logger: Logger) {
|
||||
}
|
||||
|
||||
private getBinaryData(habboAssetSWF: HabboAssetSWF, type: string, documentNameTwice: boolean) {
|
||||
let binaryName: string = habboAssetSWF.getFullClassName(type, documentNameTwice);
|
||||
let tag = habboAssetSWF.getBinaryTagByName(binaryName);
|
||||
if (tag === null) {
|
||||
binaryName = habboAssetSWF.getFullClassNameSnake(type, documentNameTwice, true);
|
||||
tag = habboAssetSWF.getBinaryTagByName(binaryName);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
private async convertXML2JSON(habboAssetSWF: HabboAssetSWF): Promise<FigureJson | null> {
|
||||
const manifestXML: DefineBinaryDataTag | null = this.getBinaryData(habboAssetSWF, "manifest", false);
|
||||
if (manifestXML !== null) {
|
||||
const result = await parser.parseStringPromise(manifestXML.binaryData);
|
||||
|
||||
return this._figureJsonMapper.mapXML(habboAssetSWF, result);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, archiveType: BundleTypes) {
|
||||
const manifestJson = await this.convertXML2JSON(habboAssetSWF);
|
||||
if (manifestJson !== null) {
|
||||
manifestJson.spritesheet = archiveType.spriteSheetType;
|
||||
|
||||
const path = outputFolder + "/" + habboAssetSWF.getDocumentClass() + ".nitro";
|
||||
const assetOuputFolder = new File(path);
|
||||
if (assetOuputFolder.exists()) {
|
||||
console.log("Figure already exists or the directory is not empty!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const nitroBundle = new NitroBundle();
|
||||
nitroBundle.addFile(habboAssetSWF.getDocumentClass() + ".json", Buffer.from(JSON.stringify(manifestJson)));
|
||||
nitroBundle.addFile(archiveType.imageData.name, archiveType.imageData.buffer);
|
||||
|
||||
const buffer = await nitroBundle.toBufferAsync();
|
||||
await fs.writeFile(path, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public async convertAsync() {
|
||||
const outputFolderFigure = new File(this._config.getValue("output.folder.figure"));
|
||||
if (!outputFolderFigure.isDirectory()) {
|
||||
outputFolderFigure.mkdirs();
|
||||
}
|
||||
|
||||
const figureConverter = this;
|
||||
|
||||
await this._figureDownloader.download(async function (habboAssetSwf: HabboAssetSWF) {
|
||||
|
||||
console.log("Attempt parsing figure: " + habboAssetSwf.getDocumentClass());
|
||||
|
||||
try {
|
||||
const spriteSheetType = await figureConverter._bundleProvider.generateSpriteSheet(habboAssetSwf, outputFolderFigure.path, "figure");
|
||||
if (spriteSheetType !== null)
|
||||
await figureConverter.fromHabboAsset(habboAssetSwf, outputFolderFigure.path, "figure", spriteSheetType);
|
||||
|
||||
} catch (e) {
|
||||
await figureConverter._logger.logErrorAsync("Figure error: " + habboAssetSwf.getDocumentClass() + e);
|
||||
console.log("Figure error: " + habboAssetSwf.getDocumentClass());
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
import Configuration from "../config/Configuration";
|
||||
import HabboAssetSWF from "../swf/HabboAssetSWF";
|
||||
import File from "../utils/File";
|
||||
import {singleton} from "tsyringe";
|
||||
import Logger from "../utils/Logger";
|
||||
|
||||
const fetch = require('node-fetch');
|
||||
const xml2js = require('xml2js');
|
||||
const parser = new xml2js.Parser(/* options */);
|
||||
|
||||
@singleton()
|
||||
export default class FigureDownloader {
|
||||
|
||||
constructor(
|
||||
private readonly _config: Configuration,
|
||||
private readonly _logger: Logger) {
|
||||
}
|
||||
|
||||
|
||||
public static types: Map<string, string> = new Map<string, string>();
|
||||
|
||||
public async download(callback: (habboAssetSwf: HabboAssetSWF) => Promise<void>) {
|
||||
const outputFolderFigure = this._config.getValue("output.folder.figure");
|
||||
const figureMap = await this.parseFigureMap();
|
||||
const map = figureMap.map;
|
||||
|
||||
for (const lib of map.lib) {
|
||||
const info = lib['$'];
|
||||
const className: string = info.id.split("\\*")[0];
|
||||
if (className === "hh_human_fx" || className === "hh_pets") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const assetOutputFolder = new File(outputFolderFigure + "/" + className);
|
||||
if (assetOutputFolder.exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!FigureDownloader.types.has(className)) {
|
||||
|
||||
const url = this._config.getValue("dynamic.download.url.figure").replace("%className%", className);
|
||||
let buffer: Buffer | null = null;
|
||||
|
||||
if (url.includes("http")) {
|
||||
const fetchData = await fetch(url);
|
||||
if (fetchData.status === 404) {
|
||||
console.log("SWF File does not exist: " + url);
|
||||
continue;
|
||||
}
|
||||
|
||||
const arrayBuffer = await fetchData.arrayBuffer();
|
||||
buffer = Buffer.from(arrayBuffer);
|
||||
} else {
|
||||
const file = new File(url);
|
||||
if (!file.exists()) {
|
||||
console.log("SWF File does not exist: " + file.path);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const newHabboAssetSWF: HabboAssetSWF = new HabboAssetSWF(buffer !== null ? buffer : url);
|
||||
await newHabboAssetSWF.setupAsync();
|
||||
|
||||
FigureDownloader.types.set(className, lib.part[0]['$'].type);
|
||||
await callback(newHabboAssetSWF);
|
||||
} catch (e) {
|
||||
await this._logger.logErrorAsync("[" + className + "]" + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async parseFigureMap() {
|
||||
const figureMapPath = this._config.getValue("figuremap.url");
|
||||
const figureFetch = await fetch(figureMapPath);
|
||||
const figureMap = await figureFetch.text();
|
||||
|
||||
return await parser.parseStringPromise(figureMap);
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
import Configuration from "../../config/Configuration";
|
||||
import HabboAssetSWF from "../../swf/HabboAssetSWF";
|
||||
import {FigureAsset, FigureAssets, FigureJson} from "./FigureJsonType";
|
||||
import {FigureXMLManifest} from "./FigureXMLTypes";
|
||||
import FigureDownloader from "../FigureDownloader";
|
||||
import {singleton} from "tsyringe";
|
||||
import BundleProvider from "../../bundle/BundleProvider";
|
||||
|
||||
@singleton()
|
||||
export default class FigureJsonMapper {
|
||||
|
||||
private static MUST_START_WITH: string = "h_";
|
||||
|
||||
constructor(
|
||||
private readonly _config: Configuration
|
||||
) {
|
||||
}
|
||||
|
||||
|
||||
public mapXML(habboAssetSWF: HabboAssetSWF, manifestXML: any): FigureJson {
|
||||
const name = habboAssetSWF.getDocumentClass();
|
||||
|
||||
return {
|
||||
name: name,
|
||||
type: FigureDownloader.types.get(name) as string,
|
||||
assets: this.mapManifestXML(habboAssetSWF, manifestXML),
|
||||
spritesheet: null as any
|
||||
};
|
||||
}
|
||||
|
||||
private mapManifestXML(habboAssetSWF: HabboAssetSWF, manifestXML: any): FigureAssets {
|
||||
const assets: any = {};
|
||||
|
||||
const figureXMLManifest: FigureXMLManifest = new FigureXMLManifest(manifestXML.manifest);
|
||||
for (const asset of figureXMLManifest.library.assets) {
|
||||
const name = asset.name;
|
||||
if (name.startsWith(FigureJsonMapper.MUST_START_WITH)) {
|
||||
let hasImage = false;
|
||||
for (const imageTag of habboAssetSWF.imageTags()) {
|
||||
if (imageTag.className.includes(name)) {
|
||||
hasImage = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasImage || !this._config.getBoolean("figure.skip.non-existing.asset.images")) {
|
||||
const figureAsset: FigureAsset = {} as any;
|
||||
figureAsset.name = name;
|
||||
figureAsset.x = parseFloat(asset.param.value.split(',')[0]);
|
||||
figureAsset.y = parseFloat(asset.param.value.split(',')[1]);
|
||||
|
||||
if (BundleProvider.imageSource.has(name)) {
|
||||
figureAsset.source = BundleProvider.imageSource.get(name) as string;
|
||||
}
|
||||
|
||||
assets[name] = figureAsset;
|
||||
/*FigureJSON.Asset asset = new FigureJSON.Asset();
|
||||
if (FFConverter.getConfig().getBoolean("figure.rotation.enabled")) {
|
||||
String[] names = assetXML.getName().split("_");
|
||||
if (this.isInteger(names[4])) {
|
||||
String firstName = names[0] + "_" + names[1] + "_" + names[2] + "_" + names[3] + "_%ROTATION%_" + names[5];
|
||||
Integer rotation = Integer.parseInt(names[4]);
|
||||
if (rotation >= 0 && rotation < 8) {
|
||||
if (assetRotations.containsKey(firstName)) {
|
||||
assetRotations.get(firstName).add(rotation);
|
||||
} else {
|
||||
List<Integer> rotations = new ArrayList<Integer>();
|
||||
rotations.add(rotation);
|
||||
assetRotations.put(firstName, rotations);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
} else {
|
||||
console.log("Image " + name + " did not decompile for some reason");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return assets;
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
import {SpriteSheetType} from "../../bundle/BundleTypes";
|
||||
|
||||
export interface FigureJson {
|
||||
type: string,
|
||||
name: string,
|
||||
spritesheet: SpriteSheetType,
|
||||
assets: FigureAssets
|
||||
}
|
||||
|
||||
export interface FigureAssets {
|
||||
[key: string]: FigureAsset
|
||||
}
|
||||
|
||||
export interface FigureAsset {
|
||||
name: string,
|
||||
source: string,
|
||||
x: number,
|
||||
y: number,
|
||||
flipH: boolean
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
export class FigureXMLManifest {
|
||||
private readonly _library: FigureXMLLibrary;
|
||||
|
||||
constructor(manifestXML: any) {
|
||||
this._library = new FigureXMLLibrary(manifestXML.library[0]);
|
||||
}
|
||||
|
||||
get library(): FigureXMLLibrary {
|
||||
return this._library;
|
||||
}
|
||||
}
|
||||
|
||||
export class FigureXMLLibrary {
|
||||
|
||||
private readonly _assets: FigureXMLAsset[];
|
||||
|
||||
constructor(libraryXML: any) {
|
||||
this._assets = [];
|
||||
for (const assetObj of libraryXML.assets) {
|
||||
for (const asset of assetObj.asset) {
|
||||
this._assets.push(new FigureXMLAsset(asset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get assets(): FigureXMLAsset[] {
|
||||
return this._assets;
|
||||
}
|
||||
}
|
||||
|
||||
export class FigureXMLAsset {
|
||||
private readonly _name: string;
|
||||
private readonly _param: FigureXMLParam;
|
||||
|
||||
constructor(assetXML: any) {
|
||||
this._name = assetXML.$.name;
|
||||
this._param = new FigureXMLParam(assetXML.param[0]);
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get param(): FigureXMLParam {
|
||||
return this._param;
|
||||
}
|
||||
}
|
||||
|
||||
export class FigureXMLParam {
|
||||
private readonly _value: string;
|
||||
|
||||
constructor(paramXML: any) {
|
||||
this._value = paramXML.$.value;
|
||||
}
|
||||
|
||||
get value(): string {
|
||||
return this._value;
|
||||
}
|
||||
}
|
@ -1,129 +0,0 @@
|
||||
import FurniJsonMapper from "./mapper/FurniJsonMapper";
|
||||
import Configuration from "../config/Configuration";
|
||||
import HabboAssetSWF from "../swf/HabboAssetSWF";
|
||||
import DefineBinaryDataTag from "../swf/tags/DefineBinaryDataTag";
|
||||
import {FurniJson} from "./mapper/FurniTypes";
|
||||
import BundleTypes from "../bundle/BundleTypes";
|
||||
import File from "../utils/File";
|
||||
import NitroBundle from "../utils/NitroBundle";
|
||||
import BundleProvider from "../bundle/BundleProvider";
|
||||
import FurnitureDownloader from "./FurnitureDownloader";
|
||||
import {singleton} from "tsyringe";
|
||||
import Logger from "../utils/Logger";
|
||||
|
||||
const xml2js = require('xml2js');
|
||||
const parser = new xml2js.Parser(/* options */);
|
||||
|
||||
const fs = require('fs').promises;
|
||||
|
||||
@singleton()
|
||||
export default class FurnitureConverter {
|
||||
|
||||
constructor(
|
||||
private readonly _furniDownloader: FurnitureDownloader,
|
||||
private readonly _furniJsonMapper: FurniJsonMapper,
|
||||
private readonly _config: Configuration,
|
||||
private readonly _bundleProvider: BundleProvider,
|
||||
private readonly _logger: Logger) {
|
||||
}
|
||||
|
||||
private static getBinaryData(habboAssetSWF: HabboAssetSWF, type: string, documentNameTwice: boolean) {
|
||||
let binaryName: string = habboAssetSWF.getFullClassName(type, documentNameTwice);
|
||||
let tag = habboAssetSWF.getBinaryTagByName(binaryName);
|
||||
if (tag === null) {
|
||||
binaryName = habboAssetSWF.getFullClassNameSnake(type, documentNameTwice, true);
|
||||
tag = habboAssetSWF.getBinaryTagByName(binaryName);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
private static async getAssetsXML(habboAssetSWF: HabboAssetSWF): Promise<any> {
|
||||
const binaryData: DefineBinaryDataTag | null = FurnitureConverter.getBinaryData(habboAssetSWF, "assets", true);
|
||||
if (binaryData !== null) {
|
||||
return await parser.parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static async getLogicXML(habboAssetSWF: HabboAssetSWF): Promise<any> {
|
||||
const binaryData: DefineBinaryDataTag | null = FurnitureConverter.getBinaryData(habboAssetSWF, "logic", true);
|
||||
if (binaryData !== null) {
|
||||
return await parser.parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static async getIndexXML(habboAssetSWF: HabboAssetSWF): Promise<any> {
|
||||
const binaryData: DefineBinaryDataTag | null = FurnitureConverter.getBinaryData(habboAssetSWF, "index", false);
|
||||
if (binaryData !== null) {
|
||||
return await parser.parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static async getVisualizationXML(habboAssetSWF: HabboAssetSWF): Promise<any> {
|
||||
const binaryData: DefineBinaryDataTag | null = FurnitureConverter.getBinaryData(habboAssetSWF, "visualization", true);
|
||||
if (binaryData !== null) {
|
||||
return await parser.parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async convertXML2JSON(habboAssetSWF: HabboAssetSWF): Promise<FurniJson | null> {
|
||||
const assetXml = await FurnitureConverter.getAssetsXML(habboAssetSWF);
|
||||
const logicXml = await FurnitureConverter.getLogicXML(habboAssetSWF);
|
||||
const indexXml = await FurnitureConverter.getIndexXML(habboAssetSWF);
|
||||
const visualizationXml = await FurnitureConverter.getVisualizationXML(habboAssetSWF);
|
||||
|
||||
return this._furniJsonMapper.mapXML(assetXml, indexXml, logicXml, visualizationXml);
|
||||
}
|
||||
|
||||
private async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, archiveType: BundleTypes) {
|
||||
const furnitureJson = await this.convertXML2JSON(habboAssetSWF);
|
||||
if (furnitureJson !== null) {
|
||||
furnitureJson.spritesheet = archiveType.spriteSheetType;
|
||||
furnitureJson.type = type;
|
||||
|
||||
const path = outputFolder + "/" + habboAssetSWF.getDocumentClass() + ".nitro";
|
||||
const assetOutputFolder = new File(path);
|
||||
if (assetOutputFolder.exists()) {
|
||||
console.log("Furniture already exists or the directory is not empty!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const nitroBundle = new NitroBundle();
|
||||
nitroBundle.addFile(habboAssetSWF.getDocumentClass() + ".json", Buffer.from(JSON.stringify(furnitureJson)));
|
||||
nitroBundle.addFile(archiveType.imageData.name, archiveType.imageData.buffer);
|
||||
|
||||
const buffer = await nitroBundle.toBufferAsync();
|
||||
await fs.writeFile(path, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public async convertAsync() {
|
||||
const outputFolderFurniture = new File(this._config.getValue("output.folder.furniture"));
|
||||
if (!outputFolderFurniture.isDirectory()) {
|
||||
outputFolderFurniture.mkdirs();
|
||||
}
|
||||
|
||||
const furnitureConverter = this;
|
||||
await this._furniDownloader.download(async function (habboAssetSwf: HabboAssetSWF, className: string) {
|
||||
console.log("Attempt parsing furniture: " + habboAssetSwf.getDocumentClass());
|
||||
|
||||
try {
|
||||
const spriteSheetType = await furnitureConverter._bundleProvider.generateSpriteSheet(habboAssetSwf, outputFolderFurniture.path, "furniture");
|
||||
if (spriteSheetType !== null) {
|
||||
await furnitureConverter.fromHabboAsset(habboAssetSwf, outputFolderFurniture.path, "furniture", spriteSheetType);
|
||||
}
|
||||
} catch (e) {
|
||||
await furnitureConverter._logger.logErrorAsync("Furniture error: " + habboAssetSwf.getDocumentClass() + " " + e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
import HabboAssetSWF from "../swf/HabboAssetSWF";
|
||||
import Configuration from "../config/Configuration";
|
||||
import {type} from "os";
|
||||
import File from "../utils/File";
|
||||
import {singleton} from "tsyringe";
|
||||
import Logger from "../utils/Logger";
|
||||
|
||||
const fs = require("fs");
|
||||
const fetch = require('node-fetch');
|
||||
const xml2js = require('xml2js');
|
||||
const parser = new xml2js.Parser(/* options */);
|
||||
const util = require('util');
|
||||
|
||||
const readFile = util.promisify(fs.readFile);
|
||||
|
||||
@singleton()
|
||||
export default class FurnitureDownloader {
|
||||
|
||||
constructor(
|
||||
private readonly _config: Configuration,
|
||||
private readonly _logger: Logger) {
|
||||
}
|
||||
|
||||
public async download(callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise<void>) {
|
||||
|
||||
const outputFolderFurniture = new File(this._config.getValue("output.folder.furniture"));
|
||||
|
||||
const furniDataObj = await this.parseFurniData();
|
||||
const furniData = furniDataObj.furnidata;
|
||||
|
||||
const roomitemtypes = furniData.roomitemtypes;
|
||||
const wallitemtypes = furniData.wallitemtypes;
|
||||
|
||||
const classNames: Array<string> = new Array<string>();
|
||||
for (const roomItem of roomitemtypes) {
|
||||
for (const furnitype of roomItem.furnitype) {
|
||||
const attributes = furnitype['$'];
|
||||
const className = attributes.classname.split("\*")[0];
|
||||
const revision = furnitype.revision[0];
|
||||
|
||||
if (classNames.includes(className)) continue;
|
||||
else classNames.push(className);
|
||||
|
||||
const assetOuputFolder = new File(outputFolderFurniture.path + "/" + className);
|
||||
if (assetOuputFolder.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await this.extractFurniture(revision, className, callback);
|
||||
}
|
||||
}
|
||||
|
||||
for (const wallItem of wallitemtypes) {
|
||||
for (const furnitype of wallItem.furnitype) {
|
||||
const attributes = furnitype['$'];
|
||||
const className = attributes.classname.split("\*")[0];
|
||||
const revision = furnitype.revision[0];
|
||||
if (classNames.includes(className)) continue;
|
||||
else classNames.push(className);
|
||||
|
||||
const assetOuputFolder = new File(outputFolderFurniture + "/" + className);
|
||||
if (assetOuputFolder.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await this.extractFurniture(revision, className, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async extractFurniture(revision: string, className: string, callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise<void>) {
|
||||
//if (/*className !== 'present_wrap' && */className !== 'holo_dragon') return;
|
||||
|
||||
const url = this._config.getValue("dynamic.download.url.furniture").replace("%revision%", revision).replace("%className%", className);
|
||||
let buffer: Buffer | null = null;
|
||||
|
||||
if (url.includes("http")) {
|
||||
const fetchData = await fetch(url);
|
||||
if (fetchData.status === 404) {
|
||||
console.log("SWF File does not exist: " + url);
|
||||
return;
|
||||
}
|
||||
|
||||
const arrayBuffer = await fetchData.arrayBuffer();
|
||||
buffer = Buffer.from(arrayBuffer);
|
||||
} else {
|
||||
const file = new File(url);
|
||||
if (!file.exists()) {
|
||||
console.log("SWF File does not exist: " + file.path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const newHabboAssetSWF: HabboAssetSWF = new HabboAssetSWF(buffer !== null ? buffer : url);
|
||||
await newHabboAssetSWF.setupAsync();
|
||||
|
||||
await callback(newHabboAssetSWF, className);
|
||||
} catch (e) {
|
||||
await this._logger.logErrorAsync(`Error with furniture: ${url} \n ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
async parseFurniData() {
|
||||
const furniDataFetch = this._config.getValue("furnidata.url");
|
||||
if (furniDataFetch.includes("http")) {
|
||||
const furniFetch = await fetch(furniDataFetch);
|
||||
const furniData = await furniFetch.text();
|
||||
|
||||
return await parser.parseStringPromise(furniData);
|
||||
} else {
|
||||
const content = await readFile(furniDataFetch);
|
||||
return await parser.parseStringPromise(content);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,360 +0,0 @@
|
||||
import {
|
||||
Action,
|
||||
Animation,
|
||||
AnimationLayer,
|
||||
AnimationLayers,
|
||||
Animations,
|
||||
Color,
|
||||
ColorLayer,
|
||||
ColorLayers,
|
||||
Colors,
|
||||
Direction,
|
||||
Directions,
|
||||
Frame,
|
||||
Frames,
|
||||
FrameSequence,
|
||||
FrameSequences,
|
||||
FurniAsset,
|
||||
FurniAssets,
|
||||
FurniJson, Gesture, Gestures,
|
||||
Layer,
|
||||
Offset, Posture, Postures,
|
||||
Visualization,
|
||||
VisualizationLayers
|
||||
} from "./FurniTypes";
|
||||
import {AssetsXML, IndexXML, LogicXML} from "./FurniXMLTypes";
|
||||
import {
|
||||
AnimationLayerXML,
|
||||
AnimationXML,
|
||||
ColorXML,
|
||||
LayerXML,
|
||||
VisualizationDataXML,
|
||||
VisualizationXML
|
||||
} from "./VisualizationXMLTypes";
|
||||
import BundleProvider from "../../bundle/BundleProvider";
|
||||
import {singleton} from "tsyringe";
|
||||
|
||||
@singleton()
|
||||
export default class FurniJsonMapper {
|
||||
private static readonly VISUALIZATION_DEFAULT_SIZE = 64;
|
||||
|
||||
private static readonly VISUALIZATION_ICON_SIZE = 1;
|
||||
|
||||
public mapXML(assets: any, indexXML: any, logic: any, visualization: any): FurniJson {
|
||||
const furniJson: FurniJson = {} as any;
|
||||
|
||||
this.mapAssetsXML(new AssetsXML(assets), furniJson);
|
||||
FurniJsonMapper.mapIndexXML(new IndexXML(indexXML.object), furniJson);
|
||||
FurniJsonMapper.mapLogicXML(new LogicXML(logic.objectData), furniJson);
|
||||
FurniJsonMapper.mapVisualizationXML(new VisualizationDataXML(visualization.visualizationData), furniJson);
|
||||
|
||||
return furniJson;
|
||||
}
|
||||
|
||||
|
||||
private mapAssetsXML(assetsXML: AssetsXML, output: FurniJson) {
|
||||
const assets: FurniAssets = {} as any;
|
||||
|
||||
for (const asset of assetsXML.assets) {
|
||||
if (!asset.name.includes("_32_")) {
|
||||
const furniAsset: FurniAsset = {} as any;
|
||||
|
||||
if (asset.source !== undefined) {
|
||||
furniAsset.source = asset.source;
|
||||
if (BundleProvider.imageSource.has(asset.source)) {
|
||||
furniAsset.source = BundleProvider.imageSource.get(asset.source) as string;
|
||||
}
|
||||
}
|
||||
|
||||
if (BundleProvider.imageSource.has(asset.name)) {
|
||||
furniAsset.source = BundleProvider.imageSource.get(asset.name) as string;
|
||||
}
|
||||
|
||||
if (asset.x !== undefined)
|
||||
furniAsset.x = parseInt(asset.x.toString());
|
||||
if (asset.y !== undefined)
|
||||
furniAsset.y = parseInt(asset.y.toString());
|
||||
furniAsset.flipH = asset.flipH as any;
|
||||
assets[asset.name] = furniAsset;
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(assets).length > 0) {
|
||||
output.assets = assets;
|
||||
}
|
||||
}
|
||||
|
||||
private static mapIndexXML(indexXML: IndexXML, output: FurniJson) {
|
||||
output.name = indexXML.type;
|
||||
output.logicType = indexXML.logic;
|
||||
output.visualizationType = indexXML.visualization;
|
||||
}
|
||||
|
||||
private static mapLogicXML(logicXML: LogicXML, output: FurniJson) {
|
||||
output.dimensions = {
|
||||
x: parseInt(logicXML.model.dimensions.x.toString()),
|
||||
y: parseInt(logicXML.model.dimensions.y.toString()),
|
||||
z: parseInt(logicXML.model.dimensions.z.toString())
|
||||
}
|
||||
|
||||
const directions: Array<number> = [];
|
||||
if (logicXML.model.directions.length === 0) {
|
||||
directions.push(0);
|
||||
} else {
|
||||
for (const direction of logicXML.model.directions) {
|
||||
directions.push(parseInt(direction.id.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (logicXML.action !== undefined) {
|
||||
const action: Action = {} as any;
|
||||
if (logicXML.action.link !== undefined) action.link = logicXML.action.link;
|
||||
if (logicXML.action.startState !== undefined) action.startState = logicXML.action.startState;
|
||||
|
||||
output.action = action;
|
||||
}
|
||||
|
||||
if (logicXML.mask !== undefined) {
|
||||
output.maskType = logicXML.mask.type;
|
||||
}
|
||||
|
||||
if (logicXML.credits !== undefined) {
|
||||
output.credits = logicXML.credits.value;
|
||||
}
|
||||
|
||||
output.directions = directions;
|
||||
}
|
||||
|
||||
private static mapVisualizationXML(visualizationData: VisualizationDataXML, output: FurniJson) {
|
||||
const visualizationsArray: Array<Visualization> = new Array<Visualization>();
|
||||
|
||||
for (const visualization of visualizationData.visualizations) {
|
||||
if (visualization.size == FurniJsonMapper.VISUALIZATION_DEFAULT_SIZE || visualization.size == FurniJsonMapper.VISUALIZATION_ICON_SIZE) {
|
||||
const visualizationJson: Visualization = {} as any;
|
||||
visualizationJson.angle = parseInt(visualization.angle.toString());
|
||||
visualizationJson.layerCount = parseInt(visualization.layerCount.toString());
|
||||
visualizationJson.size = parseInt(visualization.size.toString());
|
||||
|
||||
FurniJsonMapper.mapVisualizationLayerXML(visualization, visualizationJson);
|
||||
FurniJsonMapper.mapVisualizationDirectionXML(visualization, visualizationJson);
|
||||
FurniJsonMapper.mapVisualizationColorXML(visualization, visualizationJson);
|
||||
FurniJsonMapper.mapVisualizationAnimationXML(visualization, visualizationJson);
|
||||
FurniJsonMapper.mapVisualizationPostureXML(visualization, visualizationJson);
|
||||
FurniJsonMapper.mapVisualizationGestureXML(visualization, visualizationJson);
|
||||
|
||||
visualizationsArray.push(visualizationJson);
|
||||
}
|
||||
}
|
||||
|
||||
output.visualizations = visualizationsArray;
|
||||
}
|
||||
|
||||
private static mapVisualizationLayerXML(visXML: VisualizationXML, output: Visualization) {
|
||||
if (visXML.layers.length > 0) {
|
||||
output.layers = FurniJsonMapper.mapVisualizationLayersXML(visXML.layers);
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationLayersXML(layersXML: Array<LayerXML>): VisualizationLayers {
|
||||
const layers: VisualizationLayers = {};
|
||||
for (const layerXML of layersXML) {
|
||||
const layer: Layer = {} as any;
|
||||
if (layerXML.alpha !== undefined)
|
||||
layer.alpha = parseInt(layerXML.alpha.toString());
|
||||
layer.ink = layerXML.ink;
|
||||
layer.tag = layerXML.tag;
|
||||
|
||||
if (layerXML.x !== undefined)
|
||||
layer.x = parseInt(layerXML.x.toString());
|
||||
if (layerXML.y !== undefined)
|
||||
layer.y = parseInt(layerXML.y.toString());
|
||||
if (layerXML.z !== undefined)
|
||||
layer.z = parseInt(layerXML.z.toString());
|
||||
layer.ignoreMouse = layerXML.ignoreMouse as any;
|
||||
|
||||
layers[layerXML.id] = layer;
|
||||
}
|
||||
|
||||
return layers;
|
||||
}
|
||||
|
||||
private static mapVisualizationDirectionXML(visXML: VisualizationXML, output: Visualization) {
|
||||
if (visXML.directions.length > 0) {
|
||||
const directions: Directions = {} as any;
|
||||
for (const directionXML of visXML.directions) {
|
||||
const direction: Direction = {} as any;
|
||||
if (directionXML.layers.length > 0) {
|
||||
direction.layers = FurniJsonMapper.mapVisualizationLayersXML(directionXML.layers);
|
||||
}
|
||||
|
||||
directions[directionXML.id] = direction;
|
||||
}
|
||||
|
||||
if (Object.keys(directions).length > 0) {
|
||||
output.directions = directions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationColorXML(visXML: VisualizationXML, output: Visualization) {
|
||||
if (visXML.colors.length > 0) {
|
||||
const colors: Colors = {};
|
||||
for (const colorXML of visXML.colors) {
|
||||
if (colorXML.layers.length > 0) {
|
||||
const color: Color = {} as any;
|
||||
color.layers = FurniJsonMapper.mapVisualizationColorLayerXML(colorXML);
|
||||
|
||||
colors[colorXML.id] = color;
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(colors).length > 0) {
|
||||
output.colors = colors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationColorLayerXML(colorXML: ColorXML): ColorLayers {
|
||||
const colorLayers: ColorLayers = {};
|
||||
for (const colorLayerXML of colorXML.layers) {
|
||||
const colorLayer: ColorLayer = {} as any;
|
||||
colorLayer.color = parseInt(colorLayerXML.color, 16);
|
||||
|
||||
colorLayers[colorLayerXML.id] = colorLayer;
|
||||
}
|
||||
|
||||
return colorLayers;
|
||||
}
|
||||
|
||||
private static mapVisualizationAnimationXML(visXML: VisualizationXML, output: Visualization) {
|
||||
if (visXML.animations.length > 0) {
|
||||
const animations: Animations = {};
|
||||
for (const animationXML of visXML.animations) {
|
||||
if (animationXML.layers.length > 0) {
|
||||
const animation: Animation = {} as any;
|
||||
|
||||
if (animationXML.transitionTo !== undefined)
|
||||
animation.transitionTo = parseInt(animationXML.transitionTo.toString());
|
||||
if (animationXML.transitionFrom !== undefined)
|
||||
animation.transitionFrom = parseInt(animationXML.transitionFrom.toString());
|
||||
animation.immediateChangeFrom = animationXML.immediateChangeFrom;
|
||||
|
||||
animation.layers = FurniJsonMapper.mapVisualizationAnimationLayerXML(animationXML);
|
||||
|
||||
animations[animationXML.id] = animation;
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(animations).length > 0) {
|
||||
output.animations = animations;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationAnimationLayerXML(animationXML: AnimationXML): AnimationLayers {
|
||||
const animationLayers: AnimationLayers = {};
|
||||
for (const animationLayerXML of animationXML.layers) {
|
||||
const animationLayer: AnimationLayer = {} as any;
|
||||
|
||||
if (animationLayerXML.frameRepeat !== undefined)
|
||||
animationLayer.frameRepeat = parseInt(animationLayerXML.frameRepeat.toString());
|
||||
|
||||
if (animationLayerXML.loopCount !== undefined)
|
||||
animationLayer.loopCount = parseInt(animationLayerXML.loopCount.toString());
|
||||
|
||||
if (animationLayerXML.random !== undefined)
|
||||
animationLayer.random = parseInt(animationLayerXML.random.toString());
|
||||
|
||||
if (animationLayerXML.frameSequences.length > 0) {
|
||||
animationLayer.frameSequences = FurniJsonMapper.mapVisualizationFrameSequenceXML(animationLayerXML);
|
||||
animationLayers[animationLayerXML.id] = animationLayer;
|
||||
}
|
||||
}
|
||||
|
||||
return animationLayers;
|
||||
}
|
||||
|
||||
private static mapVisualizationFrameSequenceXML(animationLayerXML: AnimationLayerXML): FrameSequences {
|
||||
const frameSequences: FrameSequences = {};
|
||||
let frameSequenceCount = 0;
|
||||
for (const frameSequenceXML of animationLayerXML.frameSequences) {
|
||||
const frameSequence: FrameSequence = {} as any;
|
||||
|
||||
if (frameSequenceXML.frames.length > 0) {
|
||||
let frameId = 0;
|
||||
const frames: Frames = {};
|
||||
for (const frameXML of frameSequenceXML.frames) {
|
||||
const frame: Frame = {} as any;
|
||||
if (frameXML.x !== undefined)
|
||||
frame.x = parseInt(frameXML.x.toString());
|
||||
if (frameXML.y !== undefined)
|
||||
frame.y = parseInt(frameXML.y.toString());
|
||||
|
||||
if (frameXML.randomX !== undefined)
|
||||
frame.randomX = parseInt(frameXML.randomX.toString());
|
||||
|
||||
if (frameXML.randomY !== undefined)
|
||||
frame.randomY = parseInt(frameXML.randomY.toString());
|
||||
if (frameXML.id === "NaN") {
|
||||
frame.id = 0;
|
||||
} else {
|
||||
frame.id = parseInt(frameXML.id);
|
||||
}
|
||||
if (frameXML.offsets.length > 0) {
|
||||
const offsets: Array<Offset> = new Array<Offset>();
|
||||
for (const offsetXML of frameXML.offsets) {
|
||||
const offset: Offset = {} as any;
|
||||
offset.direction = offsetXML.direction;
|
||||
offset.x = offsetXML.x;
|
||||
offset.y = offsetXML.y;
|
||||
offsets.push(offset);
|
||||
}
|
||||
frame.offsets = offsets;
|
||||
}
|
||||
frames[frameId] = frame;
|
||||
frameId++;
|
||||
}
|
||||
frameSequence.loopCount = frameSequenceXML.loopCount;
|
||||
frameSequence.random = frameSequenceXML.random;
|
||||
frameSequence.frames = frames;
|
||||
frameSequences[frameSequenceCount] = frameSequence;
|
||||
}
|
||||
frameSequenceCount++;
|
||||
}
|
||||
|
||||
return frameSequences;
|
||||
}
|
||||
|
||||
private static mapVisualizationPostureXML(visXML: VisualizationXML, output: Visualization) {
|
||||
if (visXML.postures.length > 0) {
|
||||
const postures: Postures = {};
|
||||
for (const postureXML of visXML.postures) {
|
||||
const posture: Posture = {} as any;
|
||||
posture.id = postureXML.id;
|
||||
posture.animationId = postureXML.animationId;
|
||||
|
||||
postures[postureXML.id] = posture;
|
||||
}
|
||||
|
||||
if (Object.keys(postures).length > 0) {
|
||||
output.postures = postures;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationGestureXML(visXML: VisualizationXML, output: Visualization) {
|
||||
if (visXML.gestures.length > 0) {
|
||||
const gestures: Gestures = {};
|
||||
for (const gestureXML of visXML.gestures) {
|
||||
const gesture: Gesture = {} as any;
|
||||
gesture.id = gestureXML.id;
|
||||
gesture.animationId = gestureXML.animationId;
|
||||
gestures[gestureXML.id] = gesture;
|
||||
}
|
||||
|
||||
if (Object.keys(gestures).length > 0) {
|
||||
output.gestures = gestures;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,164 +0,0 @@
|
||||
import {SpriteSheetType} from "../../bundle/BundleTypes";
|
||||
|
||||
export interface FurniJson {
|
||||
type: string,
|
||||
name: string,
|
||||
visualizationType: string,
|
||||
logicType: string,
|
||||
maskType: string,
|
||||
credits: string,
|
||||
|
||||
spritesheet: SpriteSheetType,
|
||||
|
||||
dimensions: Dimensions,
|
||||
action: Action;
|
||||
directions: number[],
|
||||
assets: FurniAssets,
|
||||
visualizations: Visualization[]
|
||||
}
|
||||
|
||||
export interface Visualization {
|
||||
layerCount: number,
|
||||
angle: number,
|
||||
size: number,
|
||||
|
||||
layers: VisualizationLayers,
|
||||
directions: Directions,
|
||||
colors: Colors,
|
||||
animations: Animations,
|
||||
postures: Postures;
|
||||
gestures: Gestures
|
||||
}
|
||||
|
||||
export interface Gestures {
|
||||
[key: string]: Gesture
|
||||
}
|
||||
|
||||
export interface Gesture {
|
||||
id: string,
|
||||
animationId: number
|
||||
}
|
||||
|
||||
export interface Postures {
|
||||
[key: string]: Posture
|
||||
}
|
||||
|
||||
export interface Posture {
|
||||
id: string,
|
||||
animationId: number
|
||||
}
|
||||
|
||||
export interface Offset {
|
||||
direction: number,
|
||||
x: number,
|
||||
y: number
|
||||
}
|
||||
|
||||
export interface Frame {
|
||||
id: number,
|
||||
x: number,
|
||||
y: number,
|
||||
randomX: number,
|
||||
randomY: number,
|
||||
|
||||
offsets: Offset[]
|
||||
}
|
||||
|
||||
export interface Frames {
|
||||
[key: number]: Frame
|
||||
}
|
||||
|
||||
export interface FrameSequence {
|
||||
loopCount: number,
|
||||
random: number,
|
||||
|
||||
frames: Frames
|
||||
}
|
||||
|
||||
export interface FrameSequences {
|
||||
[key: number]: FrameSequence
|
||||
}
|
||||
|
||||
export interface AnimationLayer {
|
||||
loopCount: number,
|
||||
frameRepeat: number,
|
||||
random: number,
|
||||
|
||||
frameSequences: FrameSequences
|
||||
}
|
||||
|
||||
export interface AnimationLayers {
|
||||
[key: number]: AnimationLayer
|
||||
}
|
||||
|
||||
export interface Animations {
|
||||
[key: number]: Animation
|
||||
}
|
||||
|
||||
export interface Animation {
|
||||
transitionTo: number,
|
||||
transitionFrom: number,
|
||||
immediateChangeFrom: string,
|
||||
|
||||
layers: AnimationLayers;
|
||||
}
|
||||
|
||||
export interface ColorLayers {
|
||||
[key: number]: ColorLayer
|
||||
}
|
||||
|
||||
export interface ColorLayer {
|
||||
color: number
|
||||
}
|
||||
|
||||
export interface Colors {
|
||||
[key: number]: Color
|
||||
}
|
||||
|
||||
export interface Color {
|
||||
layers: ColorLayers;
|
||||
}
|
||||
|
||||
export interface Directions {
|
||||
[key: number]: Direction
|
||||
}
|
||||
|
||||
export interface Direction {
|
||||
layers: VisualizationLayers;
|
||||
}
|
||||
|
||||
export interface VisualizationLayers {
|
||||
[key: number]: Layer
|
||||
}
|
||||
|
||||
export interface Layer {
|
||||
alpha: number,
|
||||
x: number,
|
||||
y: number,
|
||||
z: number,
|
||||
ink: string,
|
||||
tag: string,
|
||||
ignoreMouse: boolean
|
||||
}
|
||||
|
||||
export interface Action {
|
||||
link: string,
|
||||
startState: number
|
||||
}
|
||||
|
||||
export interface Dimensions {
|
||||
x: number,
|
||||
y: number,
|
||||
z: number
|
||||
}
|
||||
|
||||
export interface FurniAssets {
|
||||
[key: string]: FurniAsset
|
||||
}
|
||||
|
||||
export interface FurniAsset {
|
||||
source: string,
|
||||
x: number,
|
||||
y: number,
|
||||
flipH: boolean
|
||||
}
|
@ -1,247 +0,0 @@
|
||||
export class AssetsXML {
|
||||
private readonly _assets: Array<AssetXML>;
|
||||
|
||||
constructor(assetsXML: any) {
|
||||
this._assets = new Array<AssetXML>();
|
||||
|
||||
for (const asset of assetsXML.assets.asset) {
|
||||
this._assets.push(new AssetXML(asset));
|
||||
}
|
||||
}
|
||||
|
||||
get assets(): Array<AssetXML> {
|
||||
return this._assets;
|
||||
}
|
||||
}
|
||||
|
||||
export class AssetXML {
|
||||
private readonly _name: string;
|
||||
private readonly _source: string | undefined;
|
||||
private readonly _x: number;
|
||||
private readonly _y: number;
|
||||
private readonly _flipH: boolean | undefined;
|
||||
private readonly _usesPalette: number | undefined;
|
||||
|
||||
constructor(asset: any) {
|
||||
const attributes = asset.$;
|
||||
|
||||
this._name = attributes.name;
|
||||
|
||||
if (attributes.source !== undefined)
|
||||
this._source = attributes.source;
|
||||
|
||||
this._x = attributes.x;
|
||||
|
||||
this._y = attributes.y;
|
||||
|
||||
if (attributes.flipH !== undefined)
|
||||
this._flipH = attributes.flipH === '1';
|
||||
|
||||
if (attributes.usesPalette !== undefined)
|
||||
this._usesPalette = attributes.usesPalette;
|
||||
}
|
||||
|
||||
get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
get source(): string | undefined {
|
||||
return this._source;
|
||||
}
|
||||
|
||||
get x(): number {
|
||||
return this._x;
|
||||
}
|
||||
|
||||
get y(): number {
|
||||
return this._y;
|
||||
}
|
||||
|
||||
get flipH(): boolean | undefined {
|
||||
return this._flipH;
|
||||
}
|
||||
|
||||
get usesPalette(): number | undefined {
|
||||
return this._usesPalette;
|
||||
}
|
||||
}
|
||||
|
||||
export class IndexXML {
|
||||
private readonly _type: string;
|
||||
private readonly _visualization: string;
|
||||
private readonly _logic: string;
|
||||
|
||||
constructor(indexXML: any) {
|
||||
const attributes = indexXML.$;
|
||||
|
||||
this._type = attributes.type;
|
||||
this._visualization = attributes.visualization;
|
||||
this._logic = attributes.logic;
|
||||
}
|
||||
|
||||
get type(): string {
|
||||
return this._type;
|
||||
}
|
||||
|
||||
get visualization(): string {
|
||||
return this._visualization;
|
||||
}
|
||||
|
||||
get logic(): string {
|
||||
return this._logic;
|
||||
}
|
||||
}
|
||||
|
||||
export class LogicXML {
|
||||
private readonly _type: string;
|
||||
private readonly _model: ModelXML;
|
||||
private readonly _action: ActionXML | undefined;
|
||||
private readonly _mask: MaskXML | undefined;
|
||||
private readonly _credits: CreditsXML | undefined;
|
||||
|
||||
constructor(logicXML: any) {
|
||||
const attributes = logicXML.$;
|
||||
this._type = attributes.type;
|
||||
|
||||
this._model = new ModelXML(logicXML.model[0]);
|
||||
if (logicXML.action !== undefined)
|
||||
this._action = new ActionXML(logicXML.action[0]);
|
||||
|
||||
if (logicXML.mask !== undefined)
|
||||
this._mask = new MaskXML(logicXML.mask[0]);
|
||||
|
||||
if (logicXML.credits !== undefined)
|
||||
this._credits = new CreditsXML(logicXML.credits[0]);
|
||||
}
|
||||
|
||||
get type(): string {
|
||||
return this._type;
|
||||
}
|
||||
|
||||
get model(): ModelXML {
|
||||
return this._model;
|
||||
}
|
||||
|
||||
get action(): ActionXML | undefined {
|
||||
return this._action;
|
||||
}
|
||||
|
||||
get mask(): MaskXML | undefined {
|
||||
return this._mask;
|
||||
}
|
||||
|
||||
get credits(): CreditsXML | undefined {
|
||||
return this._credits;
|
||||
}
|
||||
}
|
||||
|
||||
export class ModelXML {
|
||||
private readonly _dimensions: DimensionsXML;
|
||||
private readonly _directions: Array<DirectionXML>;
|
||||
|
||||
constructor(modelXML: any) {
|
||||
this._dimensions = new DimensionsXML(modelXML.dimensions[0]);
|
||||
this._directions = new Array<DirectionXML>();
|
||||
|
||||
if (Array.isArray(modelXML.directions)) {
|
||||
for (const directionParent of modelXML.directions) {
|
||||
if (Array.isArray(directionParent.direction)) {
|
||||
for (const direction of directionParent.direction) {
|
||||
this._directions.push(new DirectionXML(direction.$));
|
||||
}
|
||||
} else {
|
||||
console.log(directionParent.direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get dimensions(): DimensionsXML {
|
||||
return this._dimensions;
|
||||
}
|
||||
|
||||
get directions(): Array<DirectionXML> {
|
||||
return this._directions;
|
||||
}
|
||||
}
|
||||
|
||||
export class DimensionsXML {
|
||||
private readonly _x: number;
|
||||
private readonly _y: number;
|
||||
private readonly _z: number;
|
||||
|
||||
constructor(dimensionsXML: any) {
|
||||
const attributes = dimensionsXML.$;
|
||||
|
||||
this._x = attributes.x;
|
||||
this._y = attributes.y;
|
||||
this._z = attributes.z;
|
||||
}
|
||||
|
||||
get x(): number {
|
||||
return this._x;
|
||||
}
|
||||
|
||||
get y(): number {
|
||||
return this._y;
|
||||
}
|
||||
|
||||
get z(): number {
|
||||
return this._z;
|
||||
}
|
||||
}
|
||||
|
||||
export class DirectionXML {
|
||||
private readonly _id: number;
|
||||
|
||||
constructor(directionXML: any) {
|
||||
this._id = directionXML.id;
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
}
|
||||
|
||||
export class ActionXML {
|
||||
private readonly _link: string;
|
||||
private readonly _startState: number;
|
||||
|
||||
constructor(actionXML: any) {
|
||||
const attributes = actionXML.$;
|
||||
this._link = attributes.link;
|
||||
this._startState = attributes.startState;
|
||||
}
|
||||
|
||||
get link(): string {
|
||||
return this._link;
|
||||
}
|
||||
|
||||
get startState(): number {
|
||||
return this._startState;
|
||||
}
|
||||
}
|
||||
|
||||
export class MaskXML {
|
||||
private readonly _type: string;
|
||||
|
||||
constructor(maskXML: any) {
|
||||
this._type = maskXML.$.type;
|
||||
}
|
||||
|
||||
get type(): string {
|
||||
return this._type;
|
||||
}
|
||||
}
|
||||
|
||||
export class CreditsXML {
|
||||
private readonly _value: string;
|
||||
|
||||
constructor(creditsXML: any) {
|
||||
this._value = creditsXML.$.value;
|
||||
}
|
||||
|
||||
get value(): string {
|
||||
return this._value;
|
||||
}
|
||||
}
|
@ -1,517 +0,0 @@
|
||||
export class VisualizationDataXML {
|
||||
|
||||
private readonly _type: string;
|
||||
private readonly _visualizations: Array<VisualizationXML>;
|
||||
|
||||
constructor(visualizationXML: any) {
|
||||
this._type = visualizationXML.$.type;
|
||||
this._visualizations = new Array<VisualizationXML>();
|
||||
|
||||
if (Array.isArray(visualizationXML.graphics)) {
|
||||
for (const graphic of visualizationXML.graphics) {
|
||||
for (const visualization of graphic.visualization) {
|
||||
this._visualizations.push(new VisualizationXML(visualization));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get type(): string {
|
||||
return this._type;
|
||||
}
|
||||
|
||||
get visualizations(): Array<VisualizationXML> {
|
||||
return this._visualizations;
|
||||
}
|
||||
}
|
||||
|
||||
export class VisualizationXML {
|
||||
|
||||
private readonly _size: number;
|
||||
private readonly _layerCount: number;
|
||||
private readonly _angle: number;
|
||||
|
||||
private readonly _layers: Array<LayerXML>;
|
||||
private readonly _directions: Array<DirectionXML>;
|
||||
private readonly _colors: Array<ColorXML>;
|
||||
private readonly _animations: Array<AnimationXML>;
|
||||
private readonly _postures: Array<PostureXML>;
|
||||
private readonly _gestures: Array<GestureXML>;
|
||||
|
||||
constructor(visualizationXML: any) {
|
||||
const attributes = visualizationXML.$;
|
||||
this._size = attributes.size;
|
||||
this._layerCount = attributes.layerCount;
|
||||
this._angle = attributes.angle;
|
||||
|
||||
this._layers = new Array<LayerXML>();
|
||||
if (visualizationXML.layers !== undefined)
|
||||
for (const layerParent of visualizationXML.layers) {
|
||||
if (Array.isArray(layerParent.layer)) {
|
||||
for (const layer of layerParent.layer) {
|
||||
this._layers.push(new LayerXML(layer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._directions = new Array<DirectionXML>();
|
||||
if (visualizationXML.directions !== undefined) {
|
||||
for (const directionParent of visualizationXML.directions) {
|
||||
if (Array.isArray(directionParent.direction)) {
|
||||
for (const direction of directionParent.direction) {
|
||||
this._directions.push(new DirectionXML(direction));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._colors = new Array<ColorXML>();
|
||||
if (visualizationXML.colors !== undefined) {
|
||||
for (const colorParent of visualizationXML.colors) {
|
||||
if (Array.isArray(colorParent.color)) {
|
||||
for (const color of colorParent.color) {
|
||||
this._colors.push(new ColorXML(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._animations = new Array<AnimationXML>();
|
||||
if (visualizationXML.animations !== undefined) {
|
||||
for (const animationParent of visualizationXML.animations) {
|
||||
if (Array.isArray(animationParent.animation)) {
|
||||
for (const animation of animationParent.animation) {
|
||||
this._animations.push(new AnimationXML(animation));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._postures = new Array<PostureXML>();
|
||||
if (visualizationXML.postures !== undefined) {
|
||||
for (const postureParent of visualizationXML.postures) {
|
||||
if (Array.isArray(postureParent.posture)) {
|
||||
for (const posture of postureParent.posture) {
|
||||
this._postures.push(new PostureXML(posture));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this._gestures = new Array<GestureXML>();
|
||||
if (visualizationXML.gestures !== undefined) {
|
||||
for (const gestureParent of visualizationXML.gestures) {
|
||||
if (Array.isArray(gestureParent.gesture)) {
|
||||
for (const gesture of gestureParent.gesture) {
|
||||
this._gestures.push(new GestureXML(gesture));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get size(): number {
|
||||
return this._size;
|
||||
}
|
||||
|
||||
get layerCount(): number {
|
||||
return this._layerCount;
|
||||
}
|
||||
|
||||
get angle(): number {
|
||||
return this._angle;
|
||||
}
|
||||
|
||||
get layers(): Array<LayerXML> {
|
||||
return this._layers;
|
||||
}
|
||||
|
||||
get directions(): Array<DirectionXML> {
|
||||
return this._directions;
|
||||
}
|
||||
|
||||
get colors(): Array<ColorXML> {
|
||||
return this._colors;
|
||||
}
|
||||
|
||||
get animations(): Array<AnimationXML> {
|
||||
return this._animations;
|
||||
}
|
||||
|
||||
get postures(): Array<PostureXML> {
|
||||
return this._postures;
|
||||
}
|
||||
|
||||
get gestures(): Array<GestureXML> {
|
||||
return this._gestures;
|
||||
}
|
||||
}
|
||||
|
||||
export class LayerXML {
|
||||
private readonly _id: number;
|
||||
private readonly _alpha: number;
|
||||
private readonly _x: number;
|
||||
private readonly _y: number;
|
||||
private readonly _z: number;
|
||||
private readonly _ink: string;
|
||||
private readonly _tag: string;
|
||||
private readonly _ignoreMouse: boolean | undefined;
|
||||
|
||||
constructor(layerXML: any) {
|
||||
const attributes = layerXML.$;
|
||||
|
||||
this._id = attributes.id;
|
||||
this._alpha = attributes.alpha;
|
||||
this._x = attributes.x;
|
||||
this._y = attributes.y;
|
||||
this._z = attributes.z;
|
||||
this._ink = attributes.ink;
|
||||
this._tag = attributes.tag;
|
||||
if (attributes.ignoreMouse !== undefined) {
|
||||
this._ignoreMouse = attributes.ignoreMouse === '1';
|
||||
}
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get alpha(): number {
|
||||
return this._alpha;
|
||||
}
|
||||
|
||||
get x(): number {
|
||||
return this._x;
|
||||
}
|
||||
|
||||
get y(): number {
|
||||
return this._y;
|
||||
}
|
||||
|
||||
get z(): number {
|
||||
return this._z;
|
||||
}
|
||||
|
||||
get ink(): string {
|
||||
return this._ink;
|
||||
}
|
||||
|
||||
get tag(): string {
|
||||
return this._tag;
|
||||
}
|
||||
|
||||
get ignoreMouse(): boolean | undefined {
|
||||
return this._ignoreMouse;
|
||||
}
|
||||
}
|
||||
|
||||
export class DirectionXML {
|
||||
private readonly _id: number;
|
||||
private readonly _layers: Array<LayerXML>;
|
||||
|
||||
constructor(directionXML: any) {
|
||||
this._id = directionXML.$.id;
|
||||
|
||||
this._layers = new Array<LayerXML>();
|
||||
if (directionXML.layer !== undefined) {
|
||||
for (const layer of directionXML.layer) {
|
||||
this._layers.push(new LayerXML(layer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get layers(): Array<LayerXML> {
|
||||
return this._layers;
|
||||
}
|
||||
}
|
||||
|
||||
export class ColorXML {
|
||||
private readonly _id: number;
|
||||
private readonly _layers: Array<ColorLayerXML>;
|
||||
|
||||
constructor(colorXML: any) {
|
||||
this._id = colorXML.$.id;
|
||||
|
||||
this._layers = new Array<ColorLayerXML>();
|
||||
for (const colorLayer of colorXML.colorLayer) {
|
||||
this._layers.push(new ColorLayerXML(colorLayer));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get layers(): Array<ColorLayerXML> {
|
||||
return this._layers;
|
||||
}
|
||||
}
|
||||
|
||||
export class ColorLayerXML {
|
||||
private readonly _id: number;
|
||||
private readonly _color: string;
|
||||
|
||||
constructor(colorLayerXML: any) {
|
||||
const attributes = colorLayerXML.$;
|
||||
this._id = attributes.id;
|
||||
this._color = attributes.color;
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get color(): string {
|
||||
return this._color;
|
||||
}
|
||||
}
|
||||
|
||||
export class AnimationXML {
|
||||
private readonly _id: number;
|
||||
private readonly _transitionTo: number;
|
||||
private readonly _transitionFrom: number;
|
||||
private readonly _immediateChangeFrom: string;
|
||||
private readonly _layers: Array<AnimationLayerXML>;
|
||||
|
||||
constructor(animationXML: any) {
|
||||
const attributes = animationXML.$;
|
||||
this._id = attributes.id;
|
||||
this._transitionTo = attributes.transitionTo;
|
||||
this._transitionFrom = attributes.transitionFrom;
|
||||
this._immediateChangeFrom = attributes.immediateChangeFrom;
|
||||
|
||||
this._layers = new Array<AnimationLayerXML>();
|
||||
if (animationXML.animationLayer !== undefined) {
|
||||
for (const animationLayer of animationXML.animationLayer) {
|
||||
this._layers.push(new AnimationLayerXML(animationLayer))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get transitionTo(): number {
|
||||
return this._transitionTo;
|
||||
}
|
||||
|
||||
get transitionFrom(): number {
|
||||
return this._transitionFrom;
|
||||
}
|
||||
|
||||
get immediateChangeFrom(): string {
|
||||
return this._immediateChangeFrom;
|
||||
}
|
||||
|
||||
get layers(): Array<AnimationLayerXML> {
|
||||
return this._layers;
|
||||
}
|
||||
}
|
||||
|
||||
export class AnimationLayerXML {
|
||||
private readonly _id: number;
|
||||
private readonly _loopCount: number;
|
||||
private readonly _frameRepeat: number;
|
||||
private readonly _random: number;
|
||||
private readonly _randomStart: number;
|
||||
|
||||
private readonly _frameSequences: Array<FrameSequenceXML>;
|
||||
|
||||
constructor(animationLayerXML: any) {
|
||||
const attributes = animationLayerXML.$;
|
||||
this._id = attributes.id;
|
||||
this._loopCount = attributes.loopCount;
|
||||
this._frameRepeat = attributes.frameRepeat;
|
||||
this._random = attributes.random;
|
||||
this._randomStart = attributes.randomStart;
|
||||
|
||||
this._frameSequences = new Array<FrameSequenceXML>();
|
||||
if (animationLayerXML.frameSequence !== undefined) {
|
||||
for (const frameSequence of animationLayerXML.frameSequence) {
|
||||
this._frameSequences.push(new FrameSequenceXML(frameSequence));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get loopCount(): number {
|
||||
return this._loopCount;
|
||||
}
|
||||
|
||||
get frameRepeat(): number {
|
||||
return this._frameRepeat;
|
||||
}
|
||||
|
||||
get random(): number {
|
||||
return this._random;
|
||||
}
|
||||
|
||||
get randomStart(): number {
|
||||
return this._randomStart;
|
||||
}
|
||||
|
||||
get frameSequences(): Array<FrameSequenceXML> {
|
||||
return this._frameSequences;
|
||||
}
|
||||
}
|
||||
|
||||
export class FrameSequenceXML {
|
||||
private readonly _loopCount: number;
|
||||
private readonly _random: number;
|
||||
|
||||
private readonly _frames: Array<FrameXML>;
|
||||
|
||||
constructor(frameSequenceXML: any) {
|
||||
let attributes = frameSequenceXML.$;
|
||||
if (attributes === undefined) attributes = {};
|
||||
|
||||
this._loopCount = attributes.loopCount;
|
||||
this._random = attributes.random;
|
||||
|
||||
this._frames = new Array<FrameXML>();
|
||||
if (frameSequenceXML.frame !== undefined) {
|
||||
for (const frame of frameSequenceXML.frame) {
|
||||
this._frames.push(new FrameXML(frame));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get loopCount(): number {
|
||||
return this._loopCount;
|
||||
}
|
||||
|
||||
get random(): number {
|
||||
return this._random;
|
||||
}
|
||||
|
||||
get frames(): Array<FrameXML> {
|
||||
return this._frames;
|
||||
}
|
||||
}
|
||||
|
||||
export class FrameXML {
|
||||
private readonly _id: string;
|
||||
private readonly _x: number;
|
||||
private readonly _y: number;
|
||||
private readonly _randomX: number;
|
||||
private readonly _randomY: number;
|
||||
|
||||
private readonly _offsets: Array<OffsetXML>;
|
||||
|
||||
constructor(frameXML: any) {
|
||||
const attributes = frameXML.$;
|
||||
|
||||
this._id = attributes.id;
|
||||
this._x = attributes.x;
|
||||
this._y = attributes.y;
|
||||
this._randomX = attributes.randomX;
|
||||
this._randomY = attributes.randomY;
|
||||
|
||||
this._offsets = new Array<OffsetXML>();
|
||||
if (frameXML.offsets !== undefined) {
|
||||
for (const offsetParent of frameXML.offsets) {
|
||||
for (const offset of offsetParent.offset) {
|
||||
this._offsets.push(new OffsetXML(offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get x(): number {
|
||||
return this._x;
|
||||
}
|
||||
|
||||
get y(): number {
|
||||
return this._y;
|
||||
}
|
||||
|
||||
get randomX(): number {
|
||||
return this._randomX;
|
||||
}
|
||||
|
||||
get randomY(): number {
|
||||
return this._randomY;
|
||||
}
|
||||
|
||||
get offsets(): Array<OffsetXML> {
|
||||
return this._offsets;
|
||||
}
|
||||
}
|
||||
|
||||
export class OffsetXML {
|
||||
private readonly _direction: number;
|
||||
private readonly _x: number;
|
||||
private readonly _y: number;
|
||||
|
||||
constructor(offsetXML: any) {
|
||||
const attributes = offsetXML.$;
|
||||
|
||||
this._direction = attributes.direction;
|
||||
this._x = attributes.x;
|
||||
this._y = attributes.y;
|
||||
}
|
||||
|
||||
get direction(): number {
|
||||
return this._direction;
|
||||
}
|
||||
|
||||
get x(): number {
|
||||
return this._x;
|
||||
}
|
||||
|
||||
get y(): number {
|
||||
return this._y;
|
||||
}
|
||||
}
|
||||
|
||||
export class PostureXML {
|
||||
private readonly _id: string;
|
||||
private readonly _animationId: number;
|
||||
|
||||
constructor(postureXML: any) {
|
||||
const attributes = postureXML.$;
|
||||
|
||||
this._id = attributes.id;
|
||||
this._animationId = attributes.animationId;
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get animationId(): number {
|
||||
return this._animationId;
|
||||
}
|
||||
}
|
||||
|
||||
export class GestureXML {
|
||||
private readonly _id: string;
|
||||
private readonly _animationId: number;
|
||||
|
||||
constructor(gestureXML: any) {
|
||||
const attributes = gestureXML.$;
|
||||
|
||||
this._id = attributes.id;
|
||||
this._animationId = attributes.animationId;
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
get animationId(): number {
|
||||
return this._animationId;
|
||||
}
|
||||
}
|
9
src/mapping/json/asset/IAsset.ts
Normal file
9
src/mapping/json/asset/IAsset.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export interface IAsset
|
||||
{
|
||||
source?: string;
|
||||
x?: number;
|
||||
y?: number;
|
||||
flipH?: boolean;
|
||||
flipV?: boolean;
|
||||
usesPalette?: boolean;
|
||||
}
|
6
src/mapping/json/asset/IAssetAlias.ts
Normal file
6
src/mapping/json/asset/IAssetAlias.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export interface IAssetAlias
|
||||
{
|
||||
link: string;
|
||||
fliph: number;
|
||||
flipv: number;
|
||||
}
|
23
src/mapping/json/asset/IAssetData.ts
Normal file
23
src/mapping/json/asset/IAssetData.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { IAsset } from './IAsset';
|
||||
import { IAssetAlias } from './IAssetAlias';
|
||||
import { IAssetDimension } from './IAssetDimension';
|
||||
import { IAssetPalette } from './IAssetPalette';
|
||||
import { ISpritesheetData } from './spritesheet';
|
||||
import { IAssetVisualizationData } from './visualization';
|
||||
|
||||
export interface IAssetData {
|
||||
type?: string;
|
||||
name?: string;
|
||||
visualizationType?: string;
|
||||
logicType?: string;
|
||||
maskType?: string;
|
||||
credits?: string;
|
||||
action?: { link?: string, startState?: number };
|
||||
spritesheet?: ISpritesheetData;
|
||||
dimensions?: IAssetDimension;
|
||||
directions?: number[];
|
||||
assets?: { [index: string]: IAsset };
|
||||
aliases?: { [index: string]: IAssetAlias };
|
||||
palettes?: { [index: string]: IAssetPalette };
|
||||
visualizations?: IAssetVisualizationData[];
|
||||
}
|
6
src/mapping/json/asset/IAssetDimension.ts
Normal file
6
src/mapping/json/asset/IAssetDimension.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export interface IAssetDimension
|
||||
{
|
||||
x: number;
|
||||
y: number;
|
||||
z?: number;
|
||||
}
|
8
src/mapping/json/asset/IAssetPalette.ts
Normal file
8
src/mapping/json/asset/IAssetPalette.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export interface IAssetPalette
|
||||
{
|
||||
id?: number;
|
||||
source?: string;
|
||||
color1?: string;
|
||||
color2?: string;
|
||||
rgb?: [ number, number, number ][];
|
||||
}
|
7
src/mapping/json/asset/index.ts
Normal file
7
src/mapping/json/asset/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export * from './IAsset';
|
||||
export * from './IAssetAlias';
|
||||
export * from './IAssetData';
|
||||
export * from './IAssetDimension';
|
||||
export * from './IAssetPalette';
|
||||
export * from './spritesheet';
|
||||
export * from './visualization';
|
8
src/mapping/json/asset/spritesheet/ISpritesheetData.ts
Normal file
8
src/mapping/json/asset/spritesheet/ISpritesheetData.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { ISpritesheetFrame } from './ISpritesheetFrame';
|
||||
import { ISpritesheetMeta } from './ISpritesheetMeta';
|
||||
|
||||
export interface ISpritesheetData
|
||||
{
|
||||
meta?: ISpritesheetMeta;
|
||||
frames?: { [index: string]: ISpritesheetFrame };
|
||||
}
|
25
src/mapping/json/asset/spritesheet/ISpritesheetFrame.ts
Normal file
25
src/mapping/json/asset/spritesheet/ISpritesheetFrame.ts
Normal file
@ -0,0 +1,25 @@
|
||||
export interface ISpritesheetFrame
|
||||
{
|
||||
frame: {
|
||||
x: number;
|
||||
y: number;
|
||||
w: number;
|
||||
h: number;
|
||||
};
|
||||
rotated: boolean;
|
||||
trimmed: boolean;
|
||||
spriteSourceSize: {
|
||||
x: number;
|
||||
y: number;
|
||||
w: number;
|
||||
h: number;
|
||||
};
|
||||
sourceSize: {
|
||||
w: number;
|
||||
h: number;
|
||||
};
|
||||
pivot: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
}
|
12
src/mapping/json/asset/spritesheet/ISpritesheetMeta.ts
Normal file
12
src/mapping/json/asset/spritesheet/ISpritesheetMeta.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export interface ISpritesheetMeta
|
||||
{
|
||||
app: string;
|
||||
version: string;
|
||||
image: string;
|
||||
format: string;
|
||||
size: {
|
||||
w: number;
|
||||
h: number;
|
||||
};
|
||||
scale: string;
|
||||
}
|
3
src/mapping/json/asset/spritesheet/index.ts
Normal file
3
src/mapping/json/asset/spritesheet/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './ISpritesheetData';
|
||||
export * from './ISpritesheetFrame';
|
||||
export * from './ISpritesheetMeta';
|
@ -0,0 +1,19 @@
|
||||
import { IAssetAnimation } from './animation/IAssetAnimation';
|
||||
import { IAssetColor } from './color/IAssetColor';
|
||||
import { IAssetGesture } from './gestures/IAssetGesture';
|
||||
import { IAssetVisualizationDirection } from './IAssetVisualizationDirection';
|
||||
import { IAssetVisualizationLayer } from './IAssetVisualizationLayer';
|
||||
import { IAssetPosture } from './postures/IAssetPosture';
|
||||
|
||||
export interface IAssetVisualizationData
|
||||
{
|
||||
size?: number;
|
||||
layerCount?: number;
|
||||
angle?: number;
|
||||
layers?: { [index: string]: IAssetVisualizationLayer };
|
||||
colors?: { [index: string]: IAssetColor };
|
||||
directions?: { [index: string]: IAssetVisualizationDirection };
|
||||
animations?: { [index: string]: IAssetAnimation };
|
||||
postures?: { [index: string]: IAssetPosture };
|
||||
gestures?: { [index: string]: IAssetGesture };
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import { IAssetVisualizationLayer } from './IAssetVisualizationLayer';
|
||||
|
||||
export interface IAssetVisualizationDirection
|
||||
{
|
||||
layers?: { [index: string]: IAssetVisualizationLayer };
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
export interface IAssetVisualizationLayer
|
||||
{
|
||||
x?: number;
|
||||
y?: number;
|
||||
z?: number;
|
||||
alpha?: number;
|
||||
ink?: string;
|
||||
tag?: string;
|
||||
ignoreMouse?: boolean;
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import { IAssetAnimationLayer } from './IAssetAnimationLayer';
|
||||
|
||||
export interface IAssetAnimation
|
||||
{
|
||||
transitionTo?: number;
|
||||
transitionFrom?: number;
|
||||
immediateChangeFrom?: string;
|
||||
layers?: { [index: string]: IAssetAnimationLayer };
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import { IAssetAnimationSequence } from './IAssetAnimationSequence';
|
||||
|
||||
export interface IAssetAnimationLayer
|
||||
{
|
||||
loopCount?: number;
|
||||
frameRepeat?: number;
|
||||
random?: number;
|
||||
frameSequences?: { [index: string]: IAssetAnimationSequence };
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import { IAssetAnimationSequenceFrame } from './IAssetAnimationSequenceFrame';
|
||||
|
||||
export interface IAssetAnimationSequence
|
||||
{
|
||||
loopCount?: number;
|
||||
random?: number;
|
||||
frames?: { [index: string]: IAssetAnimationSequenceFrame };
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
import { IAssetAnimationSequenceFrameOffset } from './IAssetAnimationSequenceFrameOffset';
|
||||
|
||||
export interface IAssetAnimationSequenceFrame
|
||||
{
|
||||
id?: number;
|
||||
x?: number;
|
||||
y?: number;
|
||||
randomX?: number;
|
||||
randomY?: number;
|
||||
offsets?: { [index: string]: IAssetAnimationSequenceFrameOffset };
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
export interface IAssetAnimationSequenceFrameOffset
|
||||
{
|
||||
direction?: number;
|
||||
x?: number;
|
||||
y?: number;
|
||||
}
|
5
src/mapping/json/asset/visualization/animation/index.ts
Normal file
5
src/mapping/json/asset/visualization/animation/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export * from './IAssetAnimation';
|
||||
export * from './IAssetAnimationLayer';
|
||||
export * from './IAssetAnimationSequence';
|
||||
export * from './IAssetAnimationSequenceFrame';
|
||||
export * from './IAssetAnimationSequenceFrameOffset';
|
@ -0,0 +1,6 @@
|
||||
import { IAssetColorLayer } from './IAssetColorLayer';
|
||||
|
||||
export interface IAssetColor
|
||||
{
|
||||
layers?: { [index: string]: IAssetColorLayer };
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
export interface IAssetColorLayer
|
||||
{
|
||||
color?: number;
|
||||
}
|
2
src/mapping/json/asset/visualization/color/index.ts
Normal file
2
src/mapping/json/asset/visualization/color/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './IAssetColor';
|
||||
export * from './IAssetColorLayer';
|
@ -0,0 +1,5 @@
|
||||
export interface IAssetGesture
|
||||
{
|
||||
id?: string;
|
||||
animationId?: number;
|
||||
}
|
1
src/mapping/json/asset/visualization/gestures/index.ts
Normal file
1
src/mapping/json/asset/visualization/gestures/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './IAssetGesture';
|
7
src/mapping/json/asset/visualization/index.ts
Normal file
7
src/mapping/json/asset/visualization/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export * from './animation';
|
||||
export * from './color';
|
||||
export * from './gestures';
|
||||
export * from './IAssetVisualizationData';
|
||||
export * from './IAssetVisualizationDirection';
|
||||
export * from './IAssetVisualizationLayer';
|
||||
export * from './postures';
|
@ -0,0 +1,5 @@
|
||||
export interface IAssetPosture
|
||||
{
|
||||
id?: string;
|
||||
animationId?: number;
|
||||
}
|
1
src/mapping/json/asset/visualization/postures/index.ts
Normal file
1
src/mapping/json/asset/visualization/postures/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './IAssetPosture';
|
6
src/mapping/json/figuremap/IFigureMap.ts
Normal file
6
src/mapping/json/figuremap/IFigureMap.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { IFigureMapLibrary } from './IFigureMapLibrary';
|
||||
|
||||
export interface IFigureMap
|
||||
{
|
||||
libraries: IFigureMapLibrary[];
|
||||
}
|
8
src/mapping/json/figuremap/IFigureMapLibrary.ts
Normal file
8
src/mapping/json/figuremap/IFigureMapLibrary.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { IFigureMapLibraryPart } from './IFigureMapLibraryPart';
|
||||
|
||||
export interface IFigureMapLibrary
|
||||
{
|
||||
id: string;
|
||||
revision: number;
|
||||
parts: IFigureMapLibraryPart[];
|
||||
}
|
5
src/mapping/json/figuremap/IFigureMapLibraryPart.ts
Normal file
5
src/mapping/json/figuremap/IFigureMapLibraryPart.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export interface IFigureMapLibraryPart
|
||||
{
|
||||
id: number;
|
||||
type: string;
|
||||
}
|
3
src/mapping/json/figuremap/index.ts
Normal file
3
src/mapping/json/figuremap/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './IFigureMap';
|
||||
export * from './IFigureMapLibrary';
|
||||
export * from './IFigureMapLibraryPart';
|
11
src/mapping/json/furnidata/IFurnitureData.ts
Normal file
11
src/mapping/json/furnidata/IFurnitureData.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { IFurnitureType } from './IFurnitureType';
|
||||
|
||||
export class IFurnitureData
|
||||
{
|
||||
roomitemtypes: {
|
||||
furnitype: IFurnitureType[]
|
||||
};
|
||||
wallitemtypes: {
|
||||
furnitype: IFurnitureType[]
|
||||
};
|
||||
}
|
28
src/mapping/json/furnidata/IFurnitureType.ts
Normal file
28
src/mapping/json/furnidata/IFurnitureType.ts
Normal file
@ -0,0 +1,28 @@
|
||||
export interface IFurnitureType
|
||||
{
|
||||
id: number;
|
||||
classname: string;
|
||||
revision: number;
|
||||
category: string;
|
||||
defaultdir: number;
|
||||
xdim: number;
|
||||
ydim: number;
|
||||
partcolors: { color: string[] };
|
||||
name: string;
|
||||
description: string;
|
||||
adurl: string;
|
||||
offerid: number;
|
||||
buyout: boolean;
|
||||
rentofferid: number;
|
||||
rentbuyout: boolean;
|
||||
bc: boolean;
|
||||
excludeddynamic: boolean;
|
||||
customparams: string;
|
||||
specialtype: number;
|
||||
canstandon: boolean;
|
||||
cansiton: boolean;
|
||||
canlayon: boolean;
|
||||
furniline: string;
|
||||
environment: string;
|
||||
rare: boolean;
|
||||
}
|
2
src/mapping/json/furnidata/index.ts
Normal file
2
src/mapping/json/furnidata/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './IFurnitureData';
|
||||
export * from './IFurnitureType';
|
3
src/mapping/json/index.ts
Normal file
3
src/mapping/json/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './asset';
|
||||
export * from './figuremap';
|
||||
export * from './furnidata';
|
102
src/mapping/mappers/asset/AssetMapper.ts
Normal file
102
src/mapping/mappers/asset/AssetMapper.ts
Normal file
@ -0,0 +1,102 @@
|
||||
import { BundleProvider } from '../../../common/bundle/BundleProvider';
|
||||
import { IAsset, IAssetData, IAssetPalette } from '../../json';
|
||||
import { AssetsXML, AssetXML, PaletteXML } from '../../xml';
|
||||
import { Mapper } from './Mapper';
|
||||
|
||||
export class AssetMapper extends Mapper
|
||||
{
|
||||
public static mapXML(assets: any, output: IAssetData): void
|
||||
{
|
||||
if(!assets || !output) return;
|
||||
|
||||
AssetMapper.mapAssetsXML(new AssetsXML(assets), output);
|
||||
}
|
||||
|
||||
private static mapAssetsXML(xml: AssetsXML, output: IAssetData): void
|
||||
{
|
||||
if(!xml) return;
|
||||
|
||||
if(xml.assets !== undefined)
|
||||
{
|
||||
output.assets = {};
|
||||
|
||||
AssetMapper.mapAssetsAssetXML(xml.assets, output.assets);
|
||||
}
|
||||
|
||||
if(xml.palettes !== undefined)
|
||||
{
|
||||
output.palettes = {};
|
||||
|
||||
AssetMapper.mapAssetsPaletteXML(xml.palettes, output.palettes);
|
||||
}
|
||||
}
|
||||
|
||||
private static mapAssetsAssetXML(xml: AssetXML[], output: { [index: string]: IAsset }): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
for(const assetXML of xml)
|
||||
{
|
||||
const asset: IAsset = {};
|
||||
|
||||
if(assetXML.name !== undefined)
|
||||
{
|
||||
let isProhibited = false;
|
||||
|
||||
for(const size of AssetMapper.PROHIBITED_SIZES)
|
||||
{
|
||||
if(assetXML.name.indexOf(('_' + size + '_')) >= 0)
|
||||
{
|
||||
isProhibited = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(isProhibited) continue;
|
||||
}
|
||||
|
||||
if(assetXML.source !== undefined)
|
||||
{
|
||||
asset.source = assetXML.source;
|
||||
|
||||
if(BundleProvider.imageSource.has(assetXML.source))
|
||||
{
|
||||
asset.source = BundleProvider.imageSource.get(assetXML.source) as string;
|
||||
}
|
||||
}
|
||||
|
||||
if(assetXML.name !== undefined)
|
||||
{
|
||||
if(BundleProvider.imageSource.has(assetXML.name))
|
||||
{
|
||||
asset.source = BundleProvider.imageSource.get(assetXML.name) as string;
|
||||
}
|
||||
}
|
||||
|
||||
if(assetXML.x !== undefined) asset.x = assetXML.x;
|
||||
if(assetXML.y !== undefined) asset.y = assetXML.y;
|
||||
if(assetXML.flipH !== undefined) asset.flipH = assetXML.flipH;
|
||||
if(assetXML.flipV !== undefined) asset.flipV = assetXML.flipV;
|
||||
|
||||
output[assetXML.name] = asset;
|
||||
}
|
||||
}
|
||||
|
||||
private static mapAssetsPaletteXML(xml: PaletteXML[], output: { [index: string]: IAssetPalette }): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
for(const paletteXML of xml)
|
||||
{
|
||||
const palette: IAssetPalette = {};
|
||||
|
||||
if(paletteXML.id !== undefined) palette.id = paletteXML.id;
|
||||
if(paletteXML.source !== undefined) palette.source = paletteXML.source;
|
||||
if(paletteXML.color1 !== undefined) palette.color1 = paletteXML.color1;
|
||||
if(paletteXML.color2 !== undefined) palette.color2 = paletteXML.color2;
|
||||
|
||||
output[paletteXML.id.toString()] = palette;
|
||||
}
|
||||
}
|
||||
}
|
22
src/mapping/mappers/asset/IndexMapper.ts
Normal file
22
src/mapping/mappers/asset/IndexMapper.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { IAssetData } from '../../json';
|
||||
import { IndexXML } from '../../xml';
|
||||
import { Mapper } from './Mapper';
|
||||
|
||||
export class IndexMapper extends Mapper
|
||||
{
|
||||
public static mapXML(index: any, output: IAssetData): void
|
||||
{
|
||||
if(!index || !output) return;
|
||||
|
||||
IndexMapper.mapIndexXML(new IndexXML(index.object), output);
|
||||
}
|
||||
|
||||
private static mapIndexXML(indexXML: IndexXML, output: IAssetData): void
|
||||
{
|
||||
if(!indexXML) return;
|
||||
|
||||
if(indexXML.type !== undefined) output.name = indexXML.type;
|
||||
if(indexXML.logic !== undefined) output.logicType = indexXML.logic;
|
||||
if(indexXML.visualization !== undefined) output.visualizationType = indexXML.visualization;
|
||||
}
|
||||
}
|
67
src/mapping/mappers/asset/LogicMapper.ts
Normal file
67
src/mapping/mappers/asset/LogicMapper.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import { IAssetData } from '../../json';
|
||||
import { LogicXML } from '../../xml';
|
||||
import { Mapper } from './Mapper';
|
||||
|
||||
export class LogicMapper extends Mapper
|
||||
{
|
||||
public static mapXML(logic: any, output: IAssetData): void
|
||||
{
|
||||
if(!logic || !output) return;
|
||||
|
||||
LogicMapper.mapLogicXML(new LogicXML(logic.objectData), output);
|
||||
}
|
||||
|
||||
private static mapLogicXML(xml: LogicXML, output: IAssetData): void
|
||||
{
|
||||
if(!xml) return;
|
||||
|
||||
if(xml.model !== undefined)
|
||||
{
|
||||
if(xml.model.dimensions !== undefined)
|
||||
{
|
||||
output.dimensions = {
|
||||
x: xml.model.dimensions.x,
|
||||
y: xml.model.dimensions.y,
|
||||
z: xml.model.dimensions.z
|
||||
};
|
||||
}
|
||||
|
||||
if(xml.model.directions !== undefined)
|
||||
{
|
||||
const directions: number[] = [];
|
||||
|
||||
if(!xml.model.directions.length)
|
||||
{
|
||||
directions.push(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(const direction of xml.model.directions) directions.push(parseInt(direction.id.toString()));
|
||||
}
|
||||
|
||||
output.directions = directions;
|
||||
}
|
||||
}
|
||||
|
||||
if(xml.action !== undefined)
|
||||
{
|
||||
if(xml.action.link !== undefined)
|
||||
{
|
||||
if(!output.action) output.action = {};
|
||||
|
||||
output.action.link = xml.action.link;
|
||||
}
|
||||
|
||||
if(xml.action.startState !== undefined)
|
||||
{
|
||||
if(!output.action) output.action = {};
|
||||
|
||||
output.action.startState = xml.action.startState;
|
||||
}
|
||||
}
|
||||
|
||||
if(xml.mask !== undefined) output.maskType = xml.mask.type;
|
||||
|
||||
if(xml.credits !== undefined) output.credits = xml.credits.value;
|
||||
}
|
||||
}
|
4
src/mapping/mappers/asset/Mapper.ts
Normal file
4
src/mapping/mappers/asset/Mapper.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export class Mapper
|
||||
{
|
||||
public static PROHIBITED_SIZES: string[] = [];
|
||||
}
|
359
src/mapping/mappers/asset/VisualizationMapper.ts
Normal file
359
src/mapping/mappers/asset/VisualizationMapper.ts
Normal file
@ -0,0 +1,359 @@
|
||||
import { IAssetAnimation, IAssetAnimationLayer, IAssetAnimationSequence, IAssetAnimationSequenceFrame, IAssetAnimationSequenceFrameOffset, IAssetColor, IAssetColorLayer, IAssetData, IAssetGesture, IAssetPosture, IAssetVisualizationData, IAssetVisualizationDirection, IAssetVisualizationLayer } from '../../json';
|
||||
import { AnimationLayerXML, AnimationXML, ColorLayerXML, ColorXML, FrameOffsetXML, FrameSequenceXML, FrameXML, GestureXML, LayerXML, PostureXML, VisualDirectionXML, VisualizationDataXML, VisualizationXML } from '../../xml';
|
||||
import { Mapper } from './Mapper';
|
||||
|
||||
export class VisualizationMapper extends Mapper
|
||||
{
|
||||
public static mapXML(visualization: any, output: IAssetData): void
|
||||
{
|
||||
if(!visualization || !output) return;
|
||||
|
||||
VisualizationMapper.mapVisualizationXML(new VisualizationXML(visualization.visualizationData), output);
|
||||
}
|
||||
|
||||
private static mapVisualizationXML(xml: VisualizationXML, output: IAssetData): void
|
||||
{
|
||||
if(!xml) return;
|
||||
|
||||
if(xml.visualizations !== undefined)
|
||||
{
|
||||
output.visualizations = [];
|
||||
|
||||
VisualizationMapper.mapVisualizationDataXML(xml.visualizations, output.visualizations);
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationDataXML(xml: VisualizationDataXML[], output: IAssetVisualizationData[]): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
for(const visualizationDataXML of xml)
|
||||
{
|
||||
if(visualizationDataXML.size !== undefined)
|
||||
{
|
||||
let isProhibited = false;
|
||||
|
||||
for(const size of VisualizationMapper.PROHIBITED_SIZES)
|
||||
{
|
||||
if(visualizationDataXML.size === parseInt(size))
|
||||
{
|
||||
isProhibited = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(isProhibited) continue;
|
||||
}
|
||||
|
||||
const visualizationData: IAssetVisualizationData = {};
|
||||
|
||||
if(visualizationDataXML.angle !== undefined) visualizationData.angle = visualizationDataXML.angle;
|
||||
if(visualizationDataXML.layerCount !== undefined) visualizationData.layerCount = visualizationDataXML.layerCount;
|
||||
if(visualizationDataXML.size !== undefined) visualizationData.size = visualizationDataXML.size;
|
||||
|
||||
if(visualizationDataXML.layers !== undefined)
|
||||
{
|
||||
if(visualizationDataXML.layers.length)
|
||||
{
|
||||
visualizationData.layers = {};
|
||||
|
||||
VisualizationMapper.mapVisualizationLayerXML(visualizationDataXML.layers, visualizationData.layers);
|
||||
}
|
||||
}
|
||||
|
||||
if(visualizationDataXML.directions !== undefined)
|
||||
{
|
||||
if(visualizationDataXML.directions.length)
|
||||
{
|
||||
visualizationData.directions = {};
|
||||
|
||||
VisualizationMapper.mapVisualizationDirectionXML(visualizationDataXML.directions, visualizationData.directions);
|
||||
}
|
||||
}
|
||||
|
||||
if(visualizationDataXML.colors !== undefined)
|
||||
{
|
||||
if(visualizationDataXML.colors.length)
|
||||
{
|
||||
visualizationData.colors = {};
|
||||
|
||||
VisualizationMapper.mapVisualizationColorXML(visualizationDataXML.colors, visualizationData.colors);
|
||||
}
|
||||
}
|
||||
|
||||
if(visualizationDataXML.animations !== undefined)
|
||||
{
|
||||
if(visualizationDataXML.animations.length)
|
||||
{
|
||||
visualizationData.animations = {};
|
||||
|
||||
VisualizationMapper.mapVisualizationAnimationXML(visualizationDataXML.animations, visualizationData.animations);
|
||||
}
|
||||
}
|
||||
|
||||
if(visualizationDataXML.postures !== undefined)
|
||||
{
|
||||
if(visualizationDataXML.postures.length)
|
||||
{
|
||||
visualizationData.postures = {};
|
||||
|
||||
VisualizationMapper.mapVisualizationPostureXML(visualizationDataXML.postures, visualizationData.postures);
|
||||
}
|
||||
}
|
||||
|
||||
if(visualizationDataXML.gestures !== undefined)
|
||||
{
|
||||
if(visualizationDataXML.gestures.length)
|
||||
{
|
||||
visualizationData.gestures = {};
|
||||
|
||||
VisualizationMapper.mapVisualizationGestureXML(visualizationDataXML.gestures, visualizationData.gestures);
|
||||
}
|
||||
}
|
||||
|
||||
output.push(visualizationData);
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationLayerXML(xml: LayerXML[], output: { [index: string]: IAssetVisualizationLayer }): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
for(const layerXML of xml)
|
||||
{
|
||||
const layer: IAssetVisualizationLayer = {};
|
||||
|
||||
if(layerXML.x !== undefined) layer.x = layerXML.x;
|
||||
if(layerXML.y !== undefined) layer.y = layerXML.y;
|
||||
if(layerXML.z !== undefined) layer.z = layerXML.z;
|
||||
if(layerXML.alpha !== undefined) layer.alpha = layerXML.alpha;
|
||||
if(layerXML.ink !== undefined) layer.ink = layerXML.ink;
|
||||
if(layerXML.tag !== undefined) layer.tag = layerXML.tag;
|
||||
if(layerXML.ignoreMouse !== undefined) layer.ignoreMouse = layerXML.ignoreMouse;
|
||||
|
||||
output[layerXML.id.toString()] = layer;
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationDirectionXML(xml: VisualDirectionXML[], output: { [index: string]: IAssetVisualizationDirection }): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
for(const directionXML of xml)
|
||||
{
|
||||
const direction: IAssetVisualizationDirection = {};
|
||||
|
||||
if(directionXML.layers !== undefined)
|
||||
{
|
||||
if(directionXML.layers.length)
|
||||
{
|
||||
direction.layers = {};
|
||||
|
||||
VisualizationMapper.mapVisualizationLayerXML(directionXML.layers, direction.layers);
|
||||
}
|
||||
}
|
||||
|
||||
output[directionXML.id.toString()] = direction;
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationColorXML(xml: ColorXML[], output: { [index: string]: IAssetColor }): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
for(const colorXML of xml)
|
||||
{
|
||||
const color: IAssetColor = {};
|
||||
|
||||
if(colorXML.layers !== undefined)
|
||||
{
|
||||
if(colorXML.layers.length)
|
||||
{
|
||||
color.layers = {};
|
||||
|
||||
VisualizationMapper.mapVisualizationColorLayerXML(colorXML.layers, color.layers);
|
||||
}
|
||||
}
|
||||
|
||||
output[colorXML.id.toString()] = color;
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationColorLayerXML(xml: ColorLayerXML[], output: { [index: string]: IAssetColorLayer }): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
for(const colorLayerXML of xml)
|
||||
{
|
||||
const colorLayer: IAssetColorLayer = {};
|
||||
|
||||
if(colorLayerXML.color !== undefined) colorLayer.color = parseInt(colorLayerXML.color, 16);
|
||||
|
||||
output[colorLayerXML.id.toString()] = colorLayer;
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationAnimationXML(xml: AnimationXML[], output: { [index: string]: IAssetAnimation }): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
for(const animationXML of xml)
|
||||
{
|
||||
const animation: IAssetAnimation = {};
|
||||
|
||||
if(animationXML.transitionTo !== undefined) animation.transitionTo = animationXML.transitionTo;
|
||||
if(animationXML.transitionFrom !== undefined) animation.transitionFrom = animationXML.transitionFrom;
|
||||
if(animationXML.immediateChangeFrom !== undefined) animation.immediateChangeFrom = animationXML.immediateChangeFrom;
|
||||
|
||||
if(animationXML.layers !== undefined)
|
||||
{
|
||||
if(animationXML.layers.length)
|
||||
{
|
||||
animation.layers = {};
|
||||
|
||||
VisualizationMapper.mapVisualizationAnimationLayerXML(animationXML.layers, animation.layers);
|
||||
}
|
||||
}
|
||||
|
||||
output[animationXML.id.toString()] = animation;
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationAnimationLayerXML(xml: AnimationLayerXML[], output: { [index: string]: IAssetAnimationLayer }): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
for(const animationLayerXML of xml)
|
||||
{
|
||||
const animationLayer: IAssetAnimationLayer = {};
|
||||
|
||||
if(animationLayerXML.frameRepeat !== undefined) animationLayer.frameRepeat = animationLayerXML.frameRepeat;
|
||||
if(animationLayerXML.loopCount !== undefined) animationLayer.loopCount = animationLayerXML.loopCount;
|
||||
if(animationLayerXML.random !== undefined) animationLayer.random = animationLayerXML.random;
|
||||
|
||||
if(animationLayerXML.frameSequences !== undefined)
|
||||
{
|
||||
if(animationLayerXML.frameSequences.length)
|
||||
{
|
||||
animationLayer.frameSequences = {};
|
||||
|
||||
VisualizationMapper.mapVisualizationFrameSequenceXML(animationLayerXML.frameSequences, animationLayer.frameSequences);
|
||||
}
|
||||
}
|
||||
|
||||
output[animationLayerXML.id.toString()] = animationLayer;
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationFrameSequenceXML(xml: FrameSequenceXML[], output: { [index: string]: IAssetAnimationSequence }): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
let i = 0;
|
||||
|
||||
for(const frameSequenceXML of xml)
|
||||
{
|
||||
const frameSequence: IAssetAnimationSequence = {};
|
||||
|
||||
if(frameSequenceXML.loopCount !== undefined) frameSequence.loopCount = frameSequenceXML.loopCount;
|
||||
if(frameSequenceXML.random !== undefined) frameSequence.random = frameSequenceXML.random;
|
||||
|
||||
if(frameSequenceXML.frames !== undefined)
|
||||
{
|
||||
if(frameSequenceXML.frames.length)
|
||||
{
|
||||
frameSequence.frames = {};
|
||||
|
||||
VisualizationMapper.mapVisualizationFrameSequenceFrameXML(frameSequenceXML.frames, frameSequence.frames);
|
||||
}
|
||||
}
|
||||
|
||||
output[i.toString()] = frameSequence;
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationFrameSequenceFrameXML(xml: FrameXML[], output: { [index: string]: IAssetAnimationSequenceFrame }): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
let i = 0;
|
||||
|
||||
for(const frameXML of xml)
|
||||
{
|
||||
const frame: IAssetAnimationSequenceFrame = {};
|
||||
|
||||
if((frameXML.id === undefined) || (frameXML.id === 'NaN')) frame.id = 0;
|
||||
else frame.id = parseInt(frameXML.id);
|
||||
|
||||
if(frameXML.x !== undefined) frame.x = frameXML.x;
|
||||
if(frameXML.y !== undefined) frame.y = frameXML.y;
|
||||
if(frameXML.randomX !== undefined) frame.randomX = frameXML.randomX;
|
||||
if(frameXML.randomY !== undefined) frame.randomY = frameXML.randomY;
|
||||
|
||||
if(frameXML.offsets !== undefined)
|
||||
{
|
||||
if(frameXML.offsets.length)
|
||||
{
|
||||
frame.offsets = {};
|
||||
|
||||
VisualizationMapper.mapVisualizationFrameSequenceFrameOffsetXML(frameXML.offsets, frame.offsets);
|
||||
}
|
||||
}
|
||||
|
||||
output[i.toString()] = frame;
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationFrameSequenceFrameOffsetXML(xml: FrameOffsetXML[], output: { [index: string]: IAssetAnimationSequenceFrameOffset }): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
let i = 0;
|
||||
|
||||
for(const offsetXML of xml)
|
||||
{
|
||||
const offset: IAssetAnimationSequenceFrameOffset = {};
|
||||
|
||||
if(offsetXML.direction !== undefined) offset.direction = offsetXML.direction;
|
||||
if(offsetXML.x !== undefined) offset.x = offsetXML.x;
|
||||
if(offsetXML.y !== undefined) offset.y = offsetXML.y;
|
||||
|
||||
output[i.toString()] = offset;
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationPostureXML(xml: PostureXML[], output: { [index: string]: IAssetPosture }): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
for(const postureXML of xml)
|
||||
{
|
||||
const posture: IAssetPosture = {};
|
||||
|
||||
if(postureXML.id !== undefined) posture.id = postureXML.id;
|
||||
if(postureXML.animationId !== undefined) posture.animationId = postureXML.animationId;
|
||||
|
||||
output[postureXML.id] = posture;
|
||||
}
|
||||
}
|
||||
|
||||
private static mapVisualizationGestureXML(xml: GestureXML[], output: { [index: string]: IAssetGesture }): void
|
||||
{
|
||||
if(!xml || !xml.length) return;
|
||||
|
||||
for(const gestureXML of xml)
|
||||
{
|
||||
const gesture: IAssetGesture = {};
|
||||
|
||||
if(gestureXML.id !== undefined) gesture.id = gestureXML.id;
|
||||
if(gestureXML.animationId !== undefined) gesture.animationId = gestureXML.animationId;
|
||||
|
||||
output[gestureXML.id] = gesture;
|
||||
}
|
||||
}
|
||||
}
|
4
src/mapping/mappers/asset/index.ts
Normal file
4
src/mapping/mappers/asset/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export * from './AssetMapper';
|
||||
export * from './IndexMapper';
|
||||
export * from './LogicMapper';
|
||||
export * from './VisualizationMapper';
|
1
src/mapping/mappers/index.ts
Normal file
1
src/mapping/mappers/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './asset';
|
33
src/mapping/xml/asset/IndexXML.ts
Normal file
33
src/mapping/xml/asset/IndexXML.ts
Normal file
@ -0,0 +1,33 @@
|
||||
export class IndexXML
|
||||
{
|
||||
private readonly _type: string;
|
||||
private readonly _visualization: string;
|
||||
private readonly _logic: string;
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.type !== undefined) this._type = attributes.type;
|
||||
if(attributes.visualization !== undefined) this._visualization = attributes.visualization;
|
||||
if(attributes.logic !== undefined) this._logic = attributes.logic;
|
||||
}
|
||||
}
|
||||
|
||||
public get type(): string
|
||||
{
|
||||
return this._type;
|
||||
}
|
||||
|
||||
public get visualization(): string
|
||||
{
|
||||
return this._visualization;
|
||||
}
|
||||
|
||||
public get logic(): string
|
||||
{
|
||||
return this._logic;
|
||||
}
|
||||
}
|
61
src/mapping/xml/asset/assets/AssetXML.ts
Normal file
61
src/mapping/xml/asset/assets/AssetXML.ts
Normal file
@ -0,0 +1,61 @@
|
||||
export class AssetXML
|
||||
{
|
||||
private readonly _name: string;
|
||||
private readonly _source: string;
|
||||
private readonly _x: number;
|
||||
private readonly _y: number;
|
||||
private readonly _flipH: boolean;
|
||||
private readonly _flipV: boolean;
|
||||
private readonly _usesPalette: number;
|
||||
|
||||
constructor(asset: any)
|
||||
{
|
||||
const attributes = asset.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.name !== undefined) this._name = attributes.name;
|
||||
if(attributes.source !== undefined) this._source = attributes.source;
|
||||
if(attributes.x !== undefined) this._x = parseInt(attributes.x);
|
||||
if(attributes.x !== undefined) this._y = parseInt(attributes.y);
|
||||
if(attributes.flipH !== undefined) this._flipH = (attributes.flipH === '1');
|
||||
if(attributes.flipV !== undefined) this._flipV = (attributes.flipV === '1');
|
||||
if(attributes.usesPalette !== undefined) this._usesPalette = parseInt(attributes.usesPalette);
|
||||
}
|
||||
}
|
||||
|
||||
public get name(): string
|
||||
{
|
||||
return this._name;
|
||||
}
|
||||
|
||||
public get source(): string
|
||||
{
|
||||
return this._source;
|
||||
}
|
||||
|
||||
public get x(): number
|
||||
{
|
||||
return this._x;
|
||||
}
|
||||
|
||||
public get y(): number
|
||||
{
|
||||
return this._y;
|
||||
}
|
||||
|
||||
public get flipH(): boolean
|
||||
{
|
||||
return this._flipH;
|
||||
}
|
||||
|
||||
public get flipV(): boolean
|
||||
{
|
||||
return this._flipV;
|
||||
}
|
||||
|
||||
public get usesPalette(): number
|
||||
{
|
||||
return this._usesPalette;
|
||||
}
|
||||
}
|
35
src/mapping/xml/asset/assets/AssetsXML.ts
Normal file
35
src/mapping/xml/asset/assets/AssetsXML.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { AssetXML } from './AssetXML';
|
||||
import { PaletteXML } from './PaletteXML';
|
||||
|
||||
export class AssetsXML
|
||||
{
|
||||
private readonly _assets: AssetXML[];
|
||||
private readonly _palettes: PaletteXML[];
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
if(xml.assets !== undefined)
|
||||
{
|
||||
this._assets = [];
|
||||
|
||||
if(xml.assets.asset !== undefined) for(const asset of xml.assets.asset) this._assets.push(new AssetXML(asset));
|
||||
|
||||
if(xml.assets.palette !== undefined)
|
||||
{
|
||||
this._palettes = [];
|
||||
|
||||
for(const palette of xml.assets.palette) this._palettes.push(new PaletteXML(palette));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get assets(): AssetXML[]
|
||||
{
|
||||
return this._assets;
|
||||
}
|
||||
|
||||
public get palettes(): PaletteXML[]
|
||||
{
|
||||
return this._palettes;
|
||||
}
|
||||
}
|
40
src/mapping/xml/asset/assets/PaletteXML.ts
Normal file
40
src/mapping/xml/asset/assets/PaletteXML.ts
Normal file
@ -0,0 +1,40 @@
|
||||
export class PaletteXML
|
||||
{
|
||||
private readonly _id: number;
|
||||
private readonly _source: string;
|
||||
private readonly _color1: string;
|
||||
private readonly _color2: string;
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes)
|
||||
{
|
||||
if(attributes.id !== undefined) this._id = parseInt(attributes.id);
|
||||
if(attributes.source !== undefined) this._source = attributes.source;
|
||||
if(attributes.color1 !== undefined) this._color1 = attributes.color1;
|
||||
if(attributes.color2 !== undefined) this._color2 = attributes.color2;
|
||||
}
|
||||
}
|
||||
|
||||
public get id(): number
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get source(): string
|
||||
{
|
||||
return this._source;
|
||||
}
|
||||
|
||||
public get color1(): string
|
||||
{
|
||||
return this._color1;
|
||||
}
|
||||
|
||||
public get color2(): string
|
||||
{
|
||||
return this._color2;
|
||||
}
|
||||
}
|
3
src/mapping/xml/asset/assets/index.ts
Normal file
3
src/mapping/xml/asset/assets/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './AssetsXML';
|
||||
export * from './AssetXML';
|
||||
export * from './PaletteXML';
|
5
src/mapping/xml/asset/index.ts
Normal file
5
src/mapping/xml/asset/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export * from './assets';
|
||||
export * from './index';
|
||||
export * from './IndexXML';
|
||||
export * from './logic';
|
||||
export * from './visualization';
|
26
src/mapping/xml/asset/logic/ActionXML.ts
Normal file
26
src/mapping/xml/asset/logic/ActionXML.ts
Normal file
@ -0,0 +1,26 @@
|
||||
export class ActionXML
|
||||
{
|
||||
private readonly _link: string;
|
||||
private readonly _startState: number;
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.link !== undefined) this._link = attributes.link;
|
||||
if(attributes.startState !== undefined) this._startState = parseInt(attributes.startState);
|
||||
}
|
||||
}
|
||||
|
||||
public get link(): string
|
||||
{
|
||||
return this._link;
|
||||
}
|
||||
|
||||
public get startState(): number
|
||||
{
|
||||
return this._startState;
|
||||
}
|
||||
}
|
19
src/mapping/xml/asset/logic/CreditsXML.ts
Normal file
19
src/mapping/xml/asset/logic/CreditsXML.ts
Normal file
@ -0,0 +1,19 @@
|
||||
export class CreditsXML
|
||||
{
|
||||
private readonly _value: string;
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.value !== undefined) this._value = attributes.value;
|
||||
}
|
||||
}
|
||||
|
||||
public get value(): string
|
||||
{
|
||||
return this._value;
|
||||
}
|
||||
}
|
68
src/mapping/xml/asset/logic/LogicXML.ts
Normal file
68
src/mapping/xml/asset/logic/LogicXML.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { ActionXML } from './ActionXML';
|
||||
import { CreditsXML } from './CreditsXML';
|
||||
import { MaskXML } from './MaskXML';
|
||||
import { ModelXML } from './model/ModelXML';
|
||||
|
||||
export class LogicXML
|
||||
{
|
||||
private readonly _type: string;
|
||||
private readonly _model: ModelXML;
|
||||
private readonly _action: ActionXML;
|
||||
private readonly _mask: MaskXML;
|
||||
private readonly _credits: CreditsXML;
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.type !== undefined) this._type = attributes.type;
|
||||
}
|
||||
|
||||
if(xml.model !== undefined)
|
||||
{
|
||||
if(xml.model[0] !== undefined) this._model = new ModelXML(xml.model[0]);
|
||||
}
|
||||
|
||||
if(xml.action !== undefined)
|
||||
{
|
||||
if(xml.action[0] !== undefined) this._action = new ActionXML(xml.action[0]);
|
||||
}
|
||||
|
||||
if(xml.mask !== undefined)
|
||||
{
|
||||
if(xml.mask[0] !== undefined) this._mask = new MaskXML(xml.mask[0]);
|
||||
}
|
||||
|
||||
if(xml.credits !== undefined)
|
||||
{
|
||||
if(xml.credits[0] !== undefined) this._credits = new CreditsXML(xml.credits[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public get type(): string
|
||||
{
|
||||
return this._type;
|
||||
}
|
||||
|
||||
public get model(): ModelXML
|
||||
{
|
||||
return this._model;
|
||||
}
|
||||
|
||||
public get action(): ActionXML | undefined
|
||||
{
|
||||
return this._action;
|
||||
}
|
||||
|
||||
public get mask(): MaskXML | undefined
|
||||
{
|
||||
return this._mask;
|
||||
}
|
||||
|
||||
public get credits(): CreditsXML | undefined
|
||||
{
|
||||
return this._credits;
|
||||
}
|
||||
}
|
19
src/mapping/xml/asset/logic/MaskXML.ts
Normal file
19
src/mapping/xml/asset/logic/MaskXML.ts
Normal file
@ -0,0 +1,19 @@
|
||||
export class MaskXML
|
||||
{
|
||||
private readonly _type: string;
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.type !== undefined) this._type = attributes.type;
|
||||
}
|
||||
}
|
||||
|
||||
public get type(): string
|
||||
{
|
||||
return this._type;
|
||||
}
|
||||
}
|
5
src/mapping/xml/asset/logic/index.ts
Normal file
5
src/mapping/xml/asset/logic/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export * from './ActionXML';
|
||||
export * from './CreditsXML';
|
||||
export * from './LogicXML';
|
||||
export * from './MaskXML';
|
||||
export * from './model';
|
33
src/mapping/xml/asset/logic/model/DimensionsXML.ts
Normal file
33
src/mapping/xml/asset/logic/model/DimensionsXML.ts
Normal file
@ -0,0 +1,33 @@
|
||||
export class DimensionsXML
|
||||
{
|
||||
private readonly _x: number;
|
||||
private readonly _y: number;
|
||||
private readonly _z: number;
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.x !== undefined) this._x = parseInt(attributes.x);
|
||||
if(attributes.y !== undefined) this._y = parseInt(attributes.y);
|
||||
if(attributes.z !== undefined) this._z = parseInt(attributes.z);
|
||||
}
|
||||
}
|
||||
|
||||
public get x(): number
|
||||
{
|
||||
return this._x;
|
||||
}
|
||||
|
||||
public get y(): number
|
||||
{
|
||||
return this._y;
|
||||
}
|
||||
|
||||
public get z(): number
|
||||
{
|
||||
return this._z;
|
||||
}
|
||||
}
|
14
src/mapping/xml/asset/logic/model/ModelDirectionXML.ts
Normal file
14
src/mapping/xml/asset/logic/model/ModelDirectionXML.ts
Normal file
@ -0,0 +1,14 @@
|
||||
export class ModelDirectionXML
|
||||
{
|
||||
private readonly _id: number;
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
if(xml.id !== undefined) this._id = parseInt(xml.id);
|
||||
}
|
||||
|
||||
public get id(): number
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
}
|
39
src/mapping/xml/asset/logic/model/ModelXML.ts
Normal file
39
src/mapping/xml/asset/logic/model/ModelXML.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { DimensionsXML } from './DimensionsXML';
|
||||
import { ModelDirectionXML } from './ModelDirectionXML';
|
||||
|
||||
export class ModelXML
|
||||
{
|
||||
private readonly _dimensions: DimensionsXML;
|
||||
private readonly _directions: ModelDirectionXML[];
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
if(xml.dimensions !== undefined)
|
||||
{
|
||||
if(xml.dimensions[0] !== undefined) this._dimensions = new DimensionsXML(xml.dimensions[0]);
|
||||
}
|
||||
|
||||
if(xml.directions !== undefined)
|
||||
{
|
||||
this._directions = [];
|
||||
|
||||
if(Array.isArray(xml.directions))
|
||||
{
|
||||
for(const directionParent of xml.directions)
|
||||
{
|
||||
if(Array.isArray(directionParent.direction)) for(const direction of directionParent.direction) this._directions.push(new ModelDirectionXML(direction.$));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get dimensions(): DimensionsXML
|
||||
{
|
||||
return this._dimensions;
|
||||
}
|
||||
|
||||
public get directions(): ModelDirectionXML[]
|
||||
{
|
||||
return this._directions;
|
||||
}
|
||||
}
|
2
src/mapping/xml/asset/logic/model/index.ts
Normal file
2
src/mapping/xml/asset/logic/model/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './DimensionsXML';
|
||||
export * from './ModelDirectionXML';
|
26
src/mapping/xml/asset/visualization/GestureXML.ts
Normal file
26
src/mapping/xml/asset/visualization/GestureXML.ts
Normal file
@ -0,0 +1,26 @@
|
||||
export class GestureXML
|
||||
{
|
||||
private readonly _id: string;
|
||||
private readonly _animationId: number;
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.id !== undefined) this._id = attributes.id;
|
||||
if(attributes.animationId !== undefined) this._animationId = parseInt(attributes.animationId);
|
||||
}
|
||||
}
|
||||
|
||||
public get id(): string
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get animationId(): number
|
||||
{
|
||||
return this._animationId;
|
||||
}
|
||||
}
|
69
src/mapping/xml/asset/visualization/LayerXML.ts
Normal file
69
src/mapping/xml/asset/visualization/LayerXML.ts
Normal file
@ -0,0 +1,69 @@
|
||||
export class LayerXML
|
||||
{
|
||||
private readonly _id: number;
|
||||
private readonly _alpha: number;
|
||||
private readonly _x: number;
|
||||
private readonly _y: number;
|
||||
private readonly _z: number;
|
||||
private readonly _ink: string;
|
||||
private readonly _tag: string;
|
||||
private readonly _ignoreMouse: boolean;
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.id !== undefined) this._id = parseInt(attributes.id);
|
||||
if(attributes.alpha !== undefined) this._alpha = parseInt(attributes.alpha);
|
||||
if(attributes.x !== undefined) this._x = parseInt(attributes.x);
|
||||
if(attributes.y !== undefined) this._y = parseInt(attributes.y);
|
||||
if(attributes.z !== undefined) this._z = parseInt(attributes.z);
|
||||
if(attributes.ink !== undefined) this._ink = attributes.ink;
|
||||
if(attributes.tag !== undefined) this._tag = attributes.tag;
|
||||
|
||||
if(attributes.ignoreMouse !== undefined) this._ignoreMouse = (attributes.ignoreMouse === '1');
|
||||
}
|
||||
}
|
||||
|
||||
public get id(): number
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get alpha(): number
|
||||
{
|
||||
return this._alpha;
|
||||
}
|
||||
|
||||
public get x(): number
|
||||
{
|
||||
return this._x;
|
||||
}
|
||||
|
||||
public get y(): number
|
||||
{
|
||||
return this._y;
|
||||
}
|
||||
|
||||
public get z(): number
|
||||
{
|
||||
return this._z;
|
||||
}
|
||||
|
||||
public get ink(): string
|
||||
{
|
||||
return this._ink;
|
||||
}
|
||||
|
||||
public get tag(): string
|
||||
{
|
||||
return this._tag;
|
||||
}
|
||||
|
||||
public get ignoreMouse(): boolean
|
||||
{
|
||||
return this._ignoreMouse;
|
||||
}
|
||||
}
|
26
src/mapping/xml/asset/visualization/PostureXML.ts
Normal file
26
src/mapping/xml/asset/visualization/PostureXML.ts
Normal file
@ -0,0 +1,26 @@
|
||||
export class PostureXML
|
||||
{
|
||||
private readonly _id: string;
|
||||
private readonly _animationId: number;
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.id !== undefined) this._id = attributes.id;
|
||||
if(attributes.animationId !== undefined) this._animationId = parseInt(attributes.animationId);
|
||||
}
|
||||
}
|
||||
|
||||
public get id(): string
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get animationId(): number
|
||||
{
|
||||
return this._animationId;
|
||||
}
|
||||
}
|
34
src/mapping/xml/asset/visualization/VisualDirectionXML.ts
Normal file
34
src/mapping/xml/asset/visualization/VisualDirectionXML.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { LayerXML } from './LayerXML';
|
||||
|
||||
export class VisualDirectionXML
|
||||
{
|
||||
private readonly _id: number;
|
||||
private readonly _layers: LayerXML[];
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.id !== undefined) this._id = parseInt(attributes.id);
|
||||
}
|
||||
|
||||
if(xml.layer !== undefined)
|
||||
{
|
||||
this._layers = [];
|
||||
|
||||
for(const layer of xml.layer) this._layers.push(new LayerXML(layer));
|
||||
}
|
||||
}
|
||||
|
||||
public get id(): number
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get layers(): LayerXML[]
|
||||
{
|
||||
return this._layers;
|
||||
}
|
||||
}
|
155
src/mapping/xml/asset/visualization/VisualizationDataXML.ts
Normal file
155
src/mapping/xml/asset/visualization/VisualizationDataXML.ts
Normal file
@ -0,0 +1,155 @@
|
||||
import { AnimationXML } from './animation/AnimationXML';
|
||||
import { ColorXML } from './color/ColorXML';
|
||||
import { GestureXML } from './GestureXML';
|
||||
import { LayerXML } from './LayerXML';
|
||||
import { PostureXML } from './PostureXML';
|
||||
import { VisualDirectionXML } from './VisualDirectionXML';
|
||||
|
||||
export class VisualizationDataXML
|
||||
{
|
||||
private readonly _size: number;
|
||||
private readonly _layerCount: number;
|
||||
private readonly _angle: number;
|
||||
|
||||
private readonly _layers: LayerXML[]
|
||||
private readonly _directions: VisualDirectionXML[];
|
||||
private readonly _colors: ColorXML[];
|
||||
private readonly _animations: AnimationXML[];
|
||||
private readonly _postures: PostureXML[];
|
||||
private readonly _gestures: GestureXML[];
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.size !== undefined) this._size = parseInt(attributes.size);
|
||||
if(attributes.layerCount !== undefined) this._layerCount = parseInt(attributes.layerCount);
|
||||
if(attributes.angle !== undefined) this._angle = parseInt(attributes.angle);
|
||||
}
|
||||
|
||||
if(xml.layers !== undefined)
|
||||
{
|
||||
this._layers = [];
|
||||
|
||||
for(const layerParent of xml.layers)
|
||||
{
|
||||
if(Array.isArray(layerParent.layer))
|
||||
{
|
||||
for(const layer of layerParent.layer) this._layers.push(new LayerXML(layer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(xml.directions !== undefined)
|
||||
{
|
||||
this._directions = [];
|
||||
|
||||
for(const directionParent of xml.directions)
|
||||
{
|
||||
if(Array.isArray(directionParent.direction))
|
||||
{
|
||||
for(const direction of directionParent.direction) this._directions.push(new VisualDirectionXML(direction));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(xml.colors !== undefined)
|
||||
{
|
||||
this._colors = [];
|
||||
|
||||
for(const colorParent of xml.colors)
|
||||
{
|
||||
if(Array.isArray(colorParent.color))
|
||||
{
|
||||
for(const color of colorParent.color) this._colors.push(new ColorXML(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(xml.animations !== undefined)
|
||||
{
|
||||
this._animations = [];
|
||||
|
||||
for(const animationParent of xml.animations)
|
||||
{
|
||||
if(Array.isArray(animationParent.animation))
|
||||
{
|
||||
for(const animation of animationParent.animation) this._animations.push(new AnimationXML(animation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((xml.postures !== undefined) && xml.postures.length)
|
||||
{
|
||||
this._postures = [];
|
||||
|
||||
for(const postureParent of xml.postures)
|
||||
{
|
||||
if(Array.isArray(postureParent.posture))
|
||||
{
|
||||
for(const posture of postureParent.posture) this._postures.push(new PostureXML(posture));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(xml.gestures !== undefined)
|
||||
{
|
||||
this._gestures = [];
|
||||
|
||||
for(const gestureParent of xml.gestures)
|
||||
{
|
||||
if(Array.isArray(gestureParent.gesture))
|
||||
{
|
||||
for(const gesture of gestureParent.gesture) this._gestures.push(new GestureXML(gesture));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get size(): number
|
||||
{
|
||||
return this._size;
|
||||
}
|
||||
|
||||
public get layerCount(): number
|
||||
{
|
||||
return this._layerCount;
|
||||
}
|
||||
|
||||
public get angle(): number
|
||||
{
|
||||
return this._angle;
|
||||
}
|
||||
|
||||
public get layers(): LayerXML[]
|
||||
{
|
||||
return this._layers;
|
||||
}
|
||||
|
||||
public get directions(): VisualDirectionXML[]
|
||||
{
|
||||
return this._directions;
|
||||
}
|
||||
|
||||
public get colors(): ColorXML[]
|
||||
{
|
||||
return this._colors;
|
||||
}
|
||||
|
||||
public get animations(): AnimationXML[]
|
||||
{
|
||||
return this._animations;
|
||||
}
|
||||
|
||||
public get postures(): PostureXML[]
|
||||
{
|
||||
return this._postures;
|
||||
}
|
||||
|
||||
public get gestures(): GestureXML[]
|
||||
{
|
||||
return this._gestures;
|
||||
}
|
||||
}
|
37
src/mapping/xml/asset/visualization/VisualizationXML.ts
Normal file
37
src/mapping/xml/asset/visualization/VisualizationXML.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { VisualizationDataXML } from './VisualizationDataXML';
|
||||
|
||||
export class VisualizationXML
|
||||
{
|
||||
private readonly _type: string;
|
||||
private readonly _visualizations: VisualizationDataXML[];
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.type !== undefined) this._type = attributes.type;
|
||||
}
|
||||
|
||||
if(xml.graphics !== undefined)
|
||||
{
|
||||
this._visualizations = [];
|
||||
|
||||
if(Array.isArray(xml.graphics))
|
||||
{
|
||||
for(const graphic of xml.graphics) for(const visualization of graphic.visualization) this._visualizations.push(new VisualizationDataXML(visualization));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get type(): string
|
||||
{
|
||||
return this._type;
|
||||
}
|
||||
|
||||
public get visualizations(): VisualizationDataXML[]
|
||||
{
|
||||
return this._visualizations;
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
import { FrameSequenceXML } from './FrameSequenceXML';
|
||||
|
||||
export class AnimationLayerXML
|
||||
{
|
||||
private readonly _id: number;
|
||||
private readonly _loopCount: number;
|
||||
private readonly _frameRepeat: number;
|
||||
private readonly _random: number;
|
||||
private readonly _randomStart: number;
|
||||
|
||||
private readonly _frameSequences: FrameSequenceXML[];
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes !== undefined)
|
||||
{
|
||||
if(attributes.id !== undefined) this._id = parseInt(attributes.id);
|
||||
if(attributes.loopCount !== undefined) this._loopCount = parseInt(attributes.loopCount);
|
||||
if(attributes.frameRepeat !== undefined) this._frameRepeat = parseInt(attributes.frameRepeat);
|
||||
if(attributes.random !== undefined) this._random = parseInt(attributes.random);
|
||||
if(attributes.randomStart !== undefined) this._randomStart = parseInt(attributes.randomStart);
|
||||
}
|
||||
|
||||
if(xml.frameSequence !== undefined)
|
||||
{
|
||||
this._frameSequences = [];
|
||||
|
||||
for(const frameSequence of xml.frameSequence) this._frameSequences.push(new FrameSequenceXML(frameSequence));
|
||||
}
|
||||
}
|
||||
|
||||
public get id(): number
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get loopCount(): number
|
||||
{
|
||||
return this._loopCount;
|
||||
}
|
||||
|
||||
public get frameRepeat(): number
|
||||
{
|
||||
return this._frameRepeat;
|
||||
}
|
||||
|
||||
public get random(): number
|
||||
{
|
||||
return this._random;
|
||||
}
|
||||
|
||||
public get randomStart(): number
|
||||
{
|
||||
return this._randomStart;
|
||||
}
|
||||
|
||||
public get frameSequences(): FrameSequenceXML[]
|
||||
{
|
||||
return this._frameSequences;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user