mirror of
https://github.com/billsonnn/nitro-converter.git
synced 2024-11-26 17:30:52 +01:00
Add more converters
This commit is contained in:
parent
c3f894b231
commit
c54fddd5ea
2
.gitignore
vendored
2
.gitignore
vendored
@ -41,7 +41,7 @@ yarn-error.log
|
||||
testem.log
|
||||
/typings
|
||||
.git
|
||||
error.log
|
||||
*.log
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
|
40
src/Main.ts
40
src/Main.ts
@ -2,21 +2,55 @@ import 'reflect-metadata';
|
||||
import { container } from 'tsyringe';
|
||||
import { Configuration } from './common/config/Configuration';
|
||||
import { EffectConverter } from './converters/effect/EffectConverter';
|
||||
import { EffectMapConverter } from './converters/effectmap/EffectMapConverter';
|
||||
import { FigureConverter } from './converters/figure/FigureConverter';
|
||||
import { FigureMapConverter } from './converters/figuremap/FigureMapConverter';
|
||||
import { FurnitureConverter } from './converters/furniture/FurnitureConverter';
|
||||
import { FurnitureDataConverter } from './converters/furnituredata/FurnitureDataConverter';
|
||||
import { PetConverter } from './converters/pet/PetConverter';
|
||||
import { ProductDataConverter } from './converters/productdata/ProductDataConverter';
|
||||
|
||||
(async () =>
|
||||
{
|
||||
const config = container.resolve(Configuration);
|
||||
await config.init();
|
||||
|
||||
if(config.getBoolean('convert.figuremap'))
|
||||
{
|
||||
const figureMapConverter = container.resolve(FigureMapConverter);
|
||||
await figureMapConverter.convertAsync();
|
||||
}
|
||||
|
||||
if(config.getBoolean('convert.effectmap'))
|
||||
{
|
||||
const effectMapConverter = container.resolve(EffectMapConverter);
|
||||
await effectMapConverter.convertAsync();
|
||||
}
|
||||
|
||||
if(config.getBoolean('convert.furnidata'))
|
||||
{
|
||||
const furniDataConverter = container.resolve(FurnitureDataConverter);
|
||||
await furniDataConverter.convertAsync();
|
||||
}
|
||||
|
||||
if(config.getBoolean('convert.productdata'))
|
||||
{
|
||||
const productDataConverter = container.resolve(ProductDataConverter);
|
||||
await productDataConverter.convertAsync();
|
||||
}
|
||||
|
||||
if(config.getBoolean('convert.figure'))
|
||||
{
|
||||
const figureConverter = container.resolve(FigureConverter);
|
||||
await figureConverter.convertAsync();
|
||||
}
|
||||
|
||||
if(config.getBoolean('convert.effect'))
|
||||
{
|
||||
const effectConverter = container.resolve(EffectConverter);
|
||||
await effectConverter.convertAsync();
|
||||
}
|
||||
|
||||
if(config.getBoolean('convert.furniture'))
|
||||
{
|
||||
const furnitureConverter = container.resolve(FurnitureConverter);
|
||||
@ -28,10 +62,4 @@ import { PetConverter } from './converters/pet/PetConverter';
|
||||
const petConverter = container.resolve(PetConverter);
|
||||
await petConverter.convertAsync();
|
||||
}
|
||||
|
||||
if(config.getBoolean('convert.effect'))
|
||||
{
|
||||
const effectConverter = container.resolve(EffectConverter);
|
||||
await effectConverter.convertAsync();
|
||||
}
|
||||
})();
|
||||
|
@ -14,26 +14,22 @@ export class Configuration
|
||||
|
||||
public async init(): Promise<void>
|
||||
{
|
||||
for(const key of Object.keys(configuration)) this._config.set(key, configuration[key]);
|
||||
this.parseConfiguration(configuration);
|
||||
|
||||
await this.loadExternalVariables();
|
||||
|
||||
this.parseConfiguration(configuration);
|
||||
}
|
||||
|
||||
public async loadExternalVariables(): Promise<void>
|
||||
{
|
||||
const url = this.getValue('external_vars.url');
|
||||
const url = this.getValue('external.variables.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);
|
||||
}
|
||||
this.parseExternalVariables(content);
|
||||
}
|
||||
|
||||
catch (error)
|
||||
@ -43,19 +39,106 @@ export class Configuration
|
||||
}
|
||||
}
|
||||
|
||||
public getBoolean(key: string): boolean
|
||||
private parseConfiguration(content: Object): boolean
|
||||
{
|
||||
return this._config.get(key) === '1';
|
||||
if(!content) return false;
|
||||
|
||||
try
|
||||
{
|
||||
const regex = new RegExp(/\${(.*?)}/g);
|
||||
|
||||
for(const key of Object.keys(configuration))
|
||||
{
|
||||
if(this._config.get(key))
|
||||
{
|
||||
if(!configuration[key].length) continue;
|
||||
}
|
||||
|
||||
public getValue(key: string, value: string = ''): string
|
||||
this._config.set(key, this.interpolate(configuration[key], regex));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
catch (e)
|
||||
{
|
||||
if(this._config.has(key))
|
||||
console.log();
|
||||
console.error(e);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private parseExternalVariables(content: string): boolean
|
||||
{
|
||||
// @ts-ignore
|
||||
return this._config.get(key);
|
||||
if(!content || (content === '')) return false;
|
||||
|
||||
try
|
||||
{
|
||||
const regex = new RegExp(/\${(.*?)}/g);
|
||||
const lines: string[] = content.split('\n');
|
||||
|
||||
for(const line of lines)
|
||||
{
|
||||
const [ key, value ] = line.split('=');
|
||||
|
||||
if(key.startsWith('landing.view')) continue;
|
||||
|
||||
this._config.set(key, this.interpolate((value || ''), regex));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
catch (e)
|
||||
{
|
||||
console.log();
|
||||
console.error(e);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public interpolate(value: string, regex: RegExp = null): string
|
||||
{
|
||||
if(!regex) regex = new RegExp(/\${(.*?)}/g);
|
||||
|
||||
const pieces = value.match(regex);
|
||||
|
||||
if(pieces && pieces.length)
|
||||
{
|
||||
for(const piece of pieces)
|
||||
{
|
||||
const existing = this._config.get(this.removeInterpolateKey(piece));
|
||||
|
||||
if(existing) (value = value.replace(piece, existing));
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private removeInterpolateKey(value: string): string
|
||||
{
|
||||
return value.replace('${', '').replace('}', '');
|
||||
}
|
||||
|
||||
public getValue(key: string, value: string = ''): string
|
||||
{
|
||||
if(this._config.has(key)) return this._config.get(key);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public setValue(key: string, value: string): void
|
||||
{
|
||||
this._config.set(key, value);
|
||||
}
|
||||
|
||||
public getBoolean(key: string): boolean
|
||||
{
|
||||
const value = this.getValue(key);
|
||||
|
||||
return ((value === 'true') || (value === '1'));
|
||||
}
|
||||
}
|
||||
|
4
src/common/converters/Converter.ts
Normal file
4
src/common/converters/Converter.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export class Converter
|
||||
{
|
||||
|
||||
}
|
@ -6,8 +6,9 @@ import { HabboAssetSWF } from '../../swf/HabboAssetSWF';
|
||||
import { DefineBinaryDataTag } from '../../swf/tags/DefineBinaryDataTag';
|
||||
import { NitroBundle } from '../../utils/NitroBundle';
|
||||
import { SpriteBundle } from '../bundle/SpriteBundle';
|
||||
import { Converter } from './Converter';
|
||||
|
||||
export class SWFConverter
|
||||
export class SWFConverter extends Converter
|
||||
{
|
||||
protected async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, assetData: IAssetData, spriteBundle: SpriteBundle): Promise<void>
|
||||
{
|
||||
|
@ -1,18 +0,0 @@
|
||||
{
|
||||
"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": "1",
|
||||
"convert.effect": "1",
|
||||
"convert.pet": "1"
|
||||
}
|
22
src/configuration.json.example
Normal file
22
src/configuration.json.example
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"output.folder": "C:/nitro-converted-assets/",
|
||||
"flash.client.url": "",
|
||||
"furnidata.load.url": "",
|
||||
"productdata.load.url": "",
|
||||
"figuremap.load.url": "${flash.client.url}figuremap.xml",
|
||||
"effectmap.load.url": "${flash.client.url}effectmap.xml",
|
||||
"dynamic.download.pet.url": "${flash.client.url}%className%.swf",
|
||||
"dynamic.download.figure.url": "${flash.client.url}%className%.swf",
|
||||
"dynamic.download.effect.url": "${flash.client.url}%className%.swf",
|
||||
"flash.dynamic.download.url": "",
|
||||
"dynamic.download.furniture.url": "${flash.dynamic.download.url}%revision%/%className%.swf",
|
||||
"external.variables.url": "https://www.habbo.com/gamedata/external_variables/1",
|
||||
"convert.furnidata": "1",
|
||||
"convert.productdata": "1",
|
||||
"convert.figuremap": "1",
|
||||
"convert.effectmap": "1",
|
||||
"convert.figure": "1",
|
||||
"convert.effect": "1",
|
||||
"convert.furniture": "1",
|
||||
"convert.pet": "1"
|
||||
}
|
@ -7,7 +7,7 @@ import { IAssetData } from '../../mapping/json';
|
||||
import { AnimationMapper, ManifestMapper } from '../../mapping/mappers';
|
||||
import { HabboAssetSWF } from '../../swf/HabboAssetSWF';
|
||||
import File from '../../utils/File';
|
||||
import Logger from '../../utils/Logger';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
import { EffectDownloader } from './EffectDownloader';
|
||||
|
||||
@singleton()
|
||||
@ -28,9 +28,7 @@ export class EffectConverter extends SWFConverter
|
||||
|
||||
const spinner = ora('Preparing Effects').start();
|
||||
|
||||
const outputFolder = new File(this._configuration.getValue('output.folder.effect'));
|
||||
|
||||
if(!outputFolder.isDirectory()) outputFolder.mkdirs();
|
||||
const directory = this.getDirectory();
|
||||
|
||||
try
|
||||
{
|
||||
@ -43,7 +41,7 @@ export class EffectConverter extends SWFConverter
|
||||
const spriteBundle = await this._bundleProvider.generateSpriteSheet(habboAssetSwf);
|
||||
const assetData = await this.mapXML2JSON(habboAssetSwf, className);
|
||||
|
||||
await this.fromHabboAsset(habboAssetSwf, outputFolder.path, assetData.type, assetData, spriteBundle);
|
||||
await this.fromHabboAsset(habboAssetSwf, directory.path, assetData.type, assetData, spriteBundle);
|
||||
});
|
||||
|
||||
spinner.succeed(`Effects finished in ${ Date.now() - now }ms`);
|
||||
@ -55,23 +53,36 @@ export class EffectConverter extends SWFConverter
|
||||
}
|
||||
}
|
||||
|
||||
private getDirectory(): File
|
||||
{
|
||||
const baseFolder = new File(this._configuration.getValue('output.folder'));
|
||||
|
||||
if(!baseFolder.isDirectory()) baseFolder.mkdirs();
|
||||
|
||||
const gameDataFolder = new File(baseFolder.path + 'effect');
|
||||
|
||||
if(!gameDataFolder.isDirectory()) gameDataFolder.mkdirs();
|
||||
|
||||
return gameDataFolder;
|
||||
}
|
||||
|
||||
private async mapXML2JSON(habboAssetSWF: HabboAssetSWF, assetType: string): Promise<IAssetData>
|
||||
{
|
||||
if(!habboAssetSWF) return null;
|
||||
|
||||
const assetData: IAssetData = {};
|
||||
const output: IAssetData = {};
|
||||
|
||||
assetData.name = assetType;
|
||||
assetData.type = EffectDownloader.EFFECT_TYPES.get(assetType);
|
||||
output.name = assetType;
|
||||
output.type = EffectDownloader.EFFECT_TYPES.get(assetType);
|
||||
|
||||
const manifestXML = await EffectConverter.getManifestXML(habboAssetSWF);
|
||||
|
||||
if(manifestXML) ManifestMapper.mapXML(manifestXML, assetData);
|
||||
if(manifestXML) ManifestMapper.mapXML(manifestXML, output);
|
||||
|
||||
const animationXML = await EffectConverter.getAnimationXML(habboAssetSWF);
|
||||
|
||||
if(animationXML) AnimationMapper.mapXML(animationXML, assetData);
|
||||
if(animationXML) AnimationMapper.mapXML(animationXML, output);
|
||||
|
||||
return assetData;
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,16 @@ import { Configuration } from '../../common/config/Configuration';
|
||||
import { IEffectMap } from '../../mapping/json';
|
||||
import { HabboAssetSWF } from '../../swf/HabboAssetSWF';
|
||||
import { FileUtilities } from '../../utils/FileUtilities';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
@singleton()
|
||||
export class EffectDownloader
|
||||
{
|
||||
public static EFFECT_TYPES: Map<string, string> = new Map();
|
||||
|
||||
constructor(private readonly _configuration: Configuration)
|
||||
constructor(
|
||||
private readonly _configuration: Configuration,
|
||||
private readonly _logger: Logger)
|
||||
{}
|
||||
|
||||
public async download(callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise<void>): Promise<void>
|
||||
@ -38,6 +41,8 @@ export class EffectDownloader
|
||||
{
|
||||
console.log();
|
||||
console.error(`Error parsing ${ className }: ` + error.message);
|
||||
|
||||
this._logger.logError(`Error parsing ${ className }: ` + error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -45,7 +50,7 @@ export class EffectDownloader
|
||||
|
||||
public async parseEffectMap(): Promise<IEffectMap>
|
||||
{
|
||||
const url = this._configuration.getValue('effectmap.url');
|
||||
const url = this._configuration.getValue('effectmap.load.url');
|
||||
|
||||
if(!url || !url.length) return null;
|
||||
|
||||
@ -58,7 +63,7 @@ export class EffectDownloader
|
||||
|
||||
public async extractEffect(className: string, callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise<void>): Promise<void>
|
||||
{
|
||||
let url = this._configuration.getValue('dynamic.download.url.effect');
|
||||
let url = this._configuration.getValue('dynamic.download.effect.url');
|
||||
|
||||
if(!url || !url.length) return;
|
||||
|
||||
|
94
src/converters/effectmap/EffectMapConverter.ts
Normal file
94
src/converters/effectmap/EffectMapConverter.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import { writeFile } from 'fs/promises';
|
||||
import * as ora from 'ora';
|
||||
import { singleton } from 'tsyringe';
|
||||
import { parseStringPromise } from 'xml2js';
|
||||
import { Configuration } from '../../common/config/Configuration';
|
||||
import { Converter } from '../../common/converters/Converter';
|
||||
import { IEffectMap } from '../../mapping/json';
|
||||
import { EffectMapMapper } from '../../mapping/mappers';
|
||||
import File from '../../utils/File';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
import { EffectMapDownloader } from './EffectMapDownloader';
|
||||
|
||||
@singleton()
|
||||
export class EffectMapConverter extends Converter
|
||||
{
|
||||
constructor(
|
||||
private readonly _effectMapDownloader: EffectMapDownloader,
|
||||
private readonly _configuration: Configuration,
|
||||
private readonly _logger: Logger)
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public async convertAsync(): Promise<void>
|
||||
{
|
||||
const now = Date.now();
|
||||
|
||||
const spinner = ora('Preparing EffectMap').start();
|
||||
|
||||
const directory = this.getDirectory();
|
||||
|
||||
try
|
||||
{
|
||||
await this._effectMapDownloader.download(async (content: string) =>
|
||||
{
|
||||
spinner.text = 'Parsing EffectMap';
|
||||
|
||||
spinner.render();
|
||||
|
||||
let effectMapString = content;
|
||||
|
||||
if(!effectMapString.startsWith('{'))
|
||||
{
|
||||
const xml = await parseStringPromise(effectMapString);
|
||||
|
||||
const effectMap = await this.mapXML2JSON(xml);
|
||||
|
||||
effectMapString = JSON.stringify(effectMap);
|
||||
}
|
||||
|
||||
const path = directory.path + '/EffectMap.json';
|
||||
|
||||
await writeFile(path, effectMapString, 'utf8');
|
||||
|
||||
this._configuration.setValue('effectmap.load.url', path);
|
||||
});
|
||||
|
||||
spinner.succeed(`EffectMap finished in ${ Date.now() - now }ms`);
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
spinner.fail('EffectMap failed: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
private getDirectory(): File
|
||||
{
|
||||
const baseFolder = new File(this._configuration.getValue('output.folder'));
|
||||
|
||||
if(!baseFolder.isDirectory()) baseFolder.mkdirs();
|
||||
|
||||
const gameDataFolder = new File(baseFolder.path + '/gamedata');
|
||||
|
||||
if(!gameDataFolder.isDirectory()) gameDataFolder.mkdirs();
|
||||
|
||||
const jsonFolder = new File(gameDataFolder.path + '/json');
|
||||
|
||||
if(!jsonFolder.isDirectory()) jsonFolder.mkdirs();
|
||||
|
||||
return jsonFolder;
|
||||
}
|
||||
|
||||
private async mapXML2JSON(xml: any): Promise<IEffectMap>
|
||||
{
|
||||
if(!xml) return null;
|
||||
|
||||
const output: IEffectMap = {};
|
||||
|
||||
EffectMapMapper.mapXML(xml, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
32
src/converters/effectmap/EffectMapDownloader.ts
Normal file
32
src/converters/effectmap/EffectMapDownloader.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { singleton } from 'tsyringe';
|
||||
import { Configuration } from '../../common/config/Configuration';
|
||||
import { FileUtilities } from '../../utils/FileUtilities';
|
||||
|
||||
@singleton()
|
||||
export class EffectMapDownloader
|
||||
{
|
||||
constructor(private readonly _configuration: Configuration)
|
||||
{}
|
||||
|
||||
public async download(callback: (content: string) => Promise<void>): Promise<void>
|
||||
{
|
||||
const effectMap = await this.parseEffectMap();
|
||||
|
||||
if(!effectMap) throw new Error('invalid_effect_map');
|
||||
|
||||
callback(effectMap);
|
||||
}
|
||||
|
||||
public async parseEffectMap(): Promise<string>
|
||||
{
|
||||
const url = this._configuration.getValue('effectmap.load.url');
|
||||
|
||||
if(!url || !url.length) return null;
|
||||
|
||||
const content = await FileUtilities.readFileAsString(url);
|
||||
|
||||
if(!content || !content.length) return null;
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ import { IAssetData } from '../../mapping/json';
|
||||
import { ManifestMapper } from '../../mapping/mappers';
|
||||
import { HabboAssetSWF } from '../../swf/HabboAssetSWF';
|
||||
import File from '../../utils/File';
|
||||
import Logger from '../../utils/Logger';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
import { FigureDownloader } from './FigureDownloader';
|
||||
|
||||
@singleton()
|
||||
@ -28,9 +28,7 @@ export class FigureConverter extends SWFConverter
|
||||
|
||||
const spinner = ora('Preparing Figure').start();
|
||||
|
||||
const outputFolder = new File(this._configuration.getValue('output.folder.figure'));
|
||||
|
||||
if(!outputFolder.isDirectory()) outputFolder.mkdirs();
|
||||
const directory = this.getDirectory();
|
||||
|
||||
try
|
||||
{
|
||||
@ -43,7 +41,7 @@ export class FigureConverter extends SWFConverter
|
||||
const spriteBundle = await this._bundleProvider.generateSpriteSheet(habboAssetSwf);
|
||||
const assetData = await this.mapXML2JSON(habboAssetSwf, className);
|
||||
|
||||
await this.fromHabboAsset(habboAssetSwf, outputFolder.path, assetData.type, assetData, spriteBundle);
|
||||
await this.fromHabboAsset(habboAssetSwf, directory.path, assetData.type, assetData, spriteBundle);
|
||||
});
|
||||
|
||||
spinner.succeed(`Figures finished in ${ Date.now() - now }ms`);
|
||||
@ -55,19 +53,32 @@ export class FigureConverter extends SWFConverter
|
||||
}
|
||||
}
|
||||
|
||||
private getDirectory(): File
|
||||
{
|
||||
const baseFolder = new File(this._configuration.getValue('output.folder'));
|
||||
|
||||
if(!baseFolder.isDirectory()) baseFolder.mkdirs();
|
||||
|
||||
const gameDataFolder = new File(baseFolder.path + 'figure');
|
||||
|
||||
if(!gameDataFolder.isDirectory()) gameDataFolder.mkdirs();
|
||||
|
||||
return gameDataFolder;
|
||||
}
|
||||
|
||||
private async mapXML2JSON(habboAssetSWF: HabboAssetSWF, assetType: string): Promise<IAssetData>
|
||||
{
|
||||
if(!habboAssetSWF) return null;
|
||||
|
||||
const assetData: IAssetData = {};
|
||||
const output: IAssetData = {};
|
||||
|
||||
assetData.name = assetType;
|
||||
assetData.type = FigureDownloader.FIGURE_TYPES.get(assetType);
|
||||
output.name = assetType;
|
||||
output.type = FigureDownloader.FIGURE_TYPES.get(assetType);
|
||||
|
||||
const manifestXML = await FigureConverter.getManifestXML(habboAssetSWF);
|
||||
|
||||
if(manifestXML) ManifestMapper.mapXML(manifestXML, assetData);
|
||||
if(manifestXML) ManifestMapper.mapXML(manifestXML, output);
|
||||
|
||||
return assetData;
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
@ -3,13 +3,16 @@ import { Configuration } from '../../common/config/Configuration';
|
||||
import { IFigureMap } from '../../mapping/json';
|
||||
import { HabboAssetSWF } from '../../swf/HabboAssetSWF';
|
||||
import { FileUtilities } from '../../utils/FileUtilities';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
@singleton()
|
||||
export class FigureDownloader
|
||||
{
|
||||
public static FIGURE_TYPES: Map<string, string> = new Map();
|
||||
|
||||
constructor(private readonly _configuration: Configuration)
|
||||
constructor(
|
||||
private readonly _configuration: Configuration,
|
||||
private readonly _logger: Logger)
|
||||
{}
|
||||
|
||||
public async download(callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise<void>): Promise<void>
|
||||
@ -40,6 +43,8 @@ export class FigureDownloader
|
||||
{
|
||||
console.log();
|
||||
console.error(`Error parsing ${ className }: ` + error.message);
|
||||
|
||||
this._logger.logError(`Error parsing ${ className }: ` + error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -47,7 +52,7 @@ export class FigureDownloader
|
||||
|
||||
public async parseFigureMap(): Promise<IFigureMap>
|
||||
{
|
||||
const url = this._configuration.getValue('figuremap.url');
|
||||
const url = this._configuration.getValue('figuremap.load.url');
|
||||
|
||||
if(!url || !url.length) return null;
|
||||
|
||||
@ -60,7 +65,7 @@ export class FigureDownloader
|
||||
|
||||
public async extractFigure(className: string, callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise<void>): Promise<void>
|
||||
{
|
||||
let url = this._configuration.getValue('dynamic.download.url.figure');
|
||||
let url = this._configuration.getValue('dynamic.download.figure.url');
|
||||
|
||||
if(!url || !url.length) return;
|
||||
|
||||
|
94
src/converters/figuremap/FigureMapConverter.ts
Normal file
94
src/converters/figuremap/FigureMapConverter.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import { writeFile } from 'fs/promises';
|
||||
import * as ora from 'ora';
|
||||
import { singleton } from 'tsyringe';
|
||||
import { parseStringPromise } from 'xml2js';
|
||||
import { Configuration } from '../../common/config/Configuration';
|
||||
import { Converter } from '../../common/converters/Converter';
|
||||
import { IFigureMap } from '../../mapping/json';
|
||||
import { FigureMapMapper } from '../../mapping/mappers';
|
||||
import File from '../../utils/File';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
import { FigureMapDownloader } from './FigureMapDownloader';
|
||||
|
||||
@singleton()
|
||||
export class FigureMapConverter extends Converter
|
||||
{
|
||||
constructor(
|
||||
private readonly _figureMapDownloader: FigureMapDownloader,
|
||||
private readonly _configuration: Configuration,
|
||||
private readonly _logger: Logger)
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public async convertAsync(): Promise<void>
|
||||
{
|
||||
const now = Date.now();
|
||||
|
||||
const spinner = ora('Preparing FigureMap').start();
|
||||
|
||||
const directory = this.getDirectory();
|
||||
|
||||
try
|
||||
{
|
||||
await this._figureMapDownloader.download(async (content: string) =>
|
||||
{
|
||||
spinner.text = 'Parsing FigureMap';
|
||||
|
||||
spinner.render();
|
||||
|
||||
let figureMapString = content;
|
||||
|
||||
if(!figureMapString.startsWith('{'))
|
||||
{
|
||||
const xml = await parseStringPromise(figureMapString);
|
||||
|
||||
const figureMap = await this.mapXML2JSON(xml);
|
||||
|
||||
figureMapString = JSON.stringify(figureMap);
|
||||
}
|
||||
|
||||
const path = directory.path + '/FigureMap.json';
|
||||
|
||||
await writeFile(path, figureMapString, 'utf8');
|
||||
|
||||
this._configuration.setValue('figuremap.load.url', path);
|
||||
});
|
||||
|
||||
spinner.succeed(`FigureMap finished in ${ Date.now() - now }ms`);
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
spinner.fail('FigureMap failed: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
private getDirectory(): File
|
||||
{
|
||||
const baseFolder = new File(this._configuration.getValue('output.folder'));
|
||||
|
||||
if(!baseFolder.isDirectory()) baseFolder.mkdirs();
|
||||
|
||||
const gameDataFolder = new File(baseFolder.path + '/gamedata');
|
||||
|
||||
if(!gameDataFolder.isDirectory()) gameDataFolder.mkdirs();
|
||||
|
||||
const jsonFolder = new File(gameDataFolder.path + '/json');
|
||||
|
||||
if(!jsonFolder.isDirectory()) jsonFolder.mkdirs();
|
||||
|
||||
return jsonFolder;
|
||||
}
|
||||
|
||||
private async mapXML2JSON(xml: any): Promise<IFigureMap>
|
||||
{
|
||||
if(!xml) return null;
|
||||
|
||||
const output: IFigureMap = {};
|
||||
|
||||
FigureMapMapper.mapXML(xml, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
32
src/converters/figuremap/FigureMapDownloader.ts
Normal file
32
src/converters/figuremap/FigureMapDownloader.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { singleton } from 'tsyringe';
|
||||
import { Configuration } from '../../common/config/Configuration';
|
||||
import { FileUtilities } from '../../utils/FileUtilities';
|
||||
|
||||
@singleton()
|
||||
export class FigureMapDownloader
|
||||
{
|
||||
constructor(private readonly _configuration: Configuration)
|
||||
{}
|
||||
|
||||
public async download(callback: (content: string) => Promise<void>): Promise<void>
|
||||
{
|
||||
const figureMap = await this.parseFigureMap();
|
||||
|
||||
if(!figureMap) throw new Error('invalid_figure_map');
|
||||
|
||||
callback(figureMap);
|
||||
}
|
||||
|
||||
public async parseFigureMap(): Promise<string>
|
||||
{
|
||||
const url = this._configuration.getValue('figuremap.load.url');
|
||||
|
||||
if(!url || !url.length) return null;
|
||||
|
||||
const content = await FileUtilities.readFileAsString(url);
|
||||
|
||||
if(!content || !content.length) return null;
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ 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 { Logger } from '../../utils/Logger';
|
||||
import { FurnitureDownloader } from './FurnitureDownloader';
|
||||
|
||||
@singleton()
|
||||
@ -28,9 +28,7 @@ export class FurnitureConverter extends SWFConverter
|
||||
|
||||
const spinner = ora('Preparing Furniture').start();
|
||||
|
||||
const outputFolder = new File(this._configuration.getValue('output.folder.furniture'));
|
||||
|
||||
if(!outputFolder.isDirectory()) outputFolder.mkdirs();
|
||||
const directory = this.getDirectory();
|
||||
|
||||
try
|
||||
{
|
||||
@ -43,7 +41,7 @@ export class FurnitureConverter extends SWFConverter
|
||||
const spriteBundle = await this._bundleProvider.generateSpriteSheet(habboAssetSwf);
|
||||
const assetData = await this.mapXML2JSON(habboAssetSwf, 'furniture');
|
||||
|
||||
await this.fromHabboAsset(habboAssetSwf, outputFolder.path, 'furniture', assetData, spriteBundle);
|
||||
await this.fromHabboAsset(habboAssetSwf, directory.path, 'furniture', assetData, spriteBundle);
|
||||
});
|
||||
|
||||
spinner.succeed(`Furniture finished in ${ Date.now() - now }ms`);
|
||||
@ -55,30 +53,43 @@ export class FurnitureConverter extends SWFConverter
|
||||
}
|
||||
}
|
||||
|
||||
private getDirectory(): File
|
||||
{
|
||||
const baseFolder = new File(this._configuration.getValue('output.folder'));
|
||||
|
||||
if(!baseFolder.isDirectory()) baseFolder.mkdirs();
|
||||
|
||||
const gameDataFolder = new File(baseFolder.path + 'furniture');
|
||||
|
||||
if(!gameDataFolder.isDirectory()) gameDataFolder.mkdirs();
|
||||
|
||||
return gameDataFolder;
|
||||
}
|
||||
|
||||
private async mapXML2JSON(habboAssetSWF: HabboAssetSWF, assetType: string): Promise<IAssetData>
|
||||
{
|
||||
if(!habboAssetSWF) return null;
|
||||
|
||||
const assetData: IAssetData = {};
|
||||
const output: IAssetData = {};
|
||||
|
||||
assetData.type = assetType;
|
||||
output.type = assetType;
|
||||
|
||||
const indexXML = await FurnitureConverter.getIndexXML(habboAssetSWF);
|
||||
|
||||
if(indexXML) IndexMapper.mapXML(indexXML, assetData);
|
||||
if(indexXML) IndexMapper.mapXML(indexXML, output);
|
||||
|
||||
const assetXML = await FurnitureConverter.getAssetsXML(habboAssetSWF);
|
||||
|
||||
if(assetXML) AssetMapper.mapXML(assetXML, assetData);
|
||||
if(assetXML) AssetMapper.mapXML(assetXML, output);
|
||||
|
||||
const logicXML = await FurnitureConverter.getLogicXML(habboAssetSWF);
|
||||
|
||||
if(logicXML) LogicMapper.mapXML(logicXML, assetData);
|
||||
if(logicXML) LogicMapper.mapXML(logicXML, output);
|
||||
|
||||
const visualizationXML = await FurnitureConverter.getVisualizationXML(habboAssetSWF);
|
||||
|
||||
if(visualizationXML) VisualizationMapper.mapXML(visualizationXML, assetData);
|
||||
if(visualizationXML) VisualizationMapper.mapXML(visualizationXML, output);
|
||||
|
||||
return assetData;
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,14 @@ import { Configuration } from '../../common/config/Configuration';
|
||||
import { IFurnitureData } from '../../mapping/json';
|
||||
import { HabboAssetSWF } from '../../swf/HabboAssetSWF';
|
||||
import { FileUtilities } from '../../utils/FileUtilities';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
@singleton()
|
||||
export class FurnitureDownloader
|
||||
{
|
||||
constructor(private readonly _configuration: Configuration)
|
||||
constructor(
|
||||
private readonly _configuration: Configuration,
|
||||
private readonly _logger: Logger)
|
||||
{}
|
||||
|
||||
public async download(callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise<void>): Promise<void>
|
||||
@ -39,7 +42,7 @@ export class FurnitureDownloader
|
||||
catch (error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
console.error(`Error parsing ${ className }: ` + error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -66,7 +69,9 @@ export class FurnitureDownloader
|
||||
catch (error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
console.error(`Error parsing ${ className }: ` + error.message);
|
||||
|
||||
this._logger.logError(`Error parsing ${ className }: ` + error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,7 +80,7 @@ export class FurnitureDownloader
|
||||
|
||||
public async parseFurniData(): Promise<IFurnitureData>
|
||||
{
|
||||
const url = this._configuration.getValue('furnidata.url');
|
||||
const url = this._configuration.getValue('furnidata.load.url');
|
||||
|
||||
if(!url || !url.length) return null;
|
||||
|
||||
@ -88,7 +93,7 @@ export class FurnitureDownloader
|
||||
|
||||
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');
|
||||
let url = this._configuration.getValue('dynamic.download.furniture.url');
|
||||
|
||||
if(!url || !url.length) return;
|
||||
|
||||
|
94
src/converters/furnituredata/FurnitureDataConverter.ts
Normal file
94
src/converters/furnituredata/FurnitureDataConverter.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import { writeFile } from 'fs/promises';
|
||||
import * as ora from 'ora';
|
||||
import { singleton } from 'tsyringe';
|
||||
import { parseStringPromise } from 'xml2js';
|
||||
import { Configuration } from '../../common/config/Configuration';
|
||||
import { Converter } from '../../common/converters/Converter';
|
||||
import { IFurnitureData } from '../../mapping/json';
|
||||
import { FurnitureDataMapper } from '../../mapping/mappers';
|
||||
import File from '../../utils/File';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
import { FurnitureDataDownloader } from './FurnitureDataDownloader';
|
||||
|
||||
@singleton()
|
||||
export class FurnitureDataConverter extends Converter
|
||||
{
|
||||
constructor(
|
||||
private readonly _furnitureDataDownloader: FurnitureDataDownloader,
|
||||
private readonly _configuration: Configuration,
|
||||
private readonly _logger: Logger)
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public async convertAsync(): Promise<void>
|
||||
{
|
||||
const now = Date.now();
|
||||
|
||||
const spinner = ora('Preparing FurnitureData').start();
|
||||
|
||||
const directory = this.getDirectory();
|
||||
|
||||
try
|
||||
{
|
||||
await this._furnitureDataDownloader.download(async (content: string) =>
|
||||
{
|
||||
spinner.text = 'Parsing FurnitureData';
|
||||
|
||||
spinner.render();
|
||||
|
||||
let furnitureDataString = content;
|
||||
|
||||
if(!furnitureDataString.startsWith('{'))
|
||||
{
|
||||
const xml = await parseStringPromise(furnitureDataString);
|
||||
|
||||
const furnitureData = await this.mapXML2JSON(xml);
|
||||
|
||||
furnitureDataString = JSON.stringify(furnitureData);
|
||||
}
|
||||
|
||||
const path = directory.path + '/FurnitureData.json';
|
||||
|
||||
await writeFile(path, furnitureDataString, 'utf8');
|
||||
|
||||
this._configuration.setValue('furnidata.load.url', path);
|
||||
});
|
||||
|
||||
spinner.succeed(`FurnitureData finished in ${ Date.now() - now }ms`);
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
spinner.fail('FurnitureData failed: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
private getDirectory(): File
|
||||
{
|
||||
const baseFolder = new File(this._configuration.getValue('output.folder'));
|
||||
|
||||
if(!baseFolder.isDirectory()) baseFolder.mkdirs();
|
||||
|
||||
const gameDataFolder = new File(baseFolder.path + '/gamedata');
|
||||
|
||||
if(!gameDataFolder.isDirectory()) gameDataFolder.mkdirs();
|
||||
|
||||
const jsonFolder = new File(gameDataFolder.path + '/json');
|
||||
|
||||
if(!jsonFolder.isDirectory()) jsonFolder.mkdirs();
|
||||
|
||||
return jsonFolder;
|
||||
}
|
||||
|
||||
private async mapXML2JSON(xml: any): Promise<IFurnitureData>
|
||||
{
|
||||
if(!xml) return null;
|
||||
|
||||
const output: IFurnitureData = {};
|
||||
|
||||
FurnitureDataMapper.mapXML(xml, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
32
src/converters/furnituredata/FurnitureDataDownloader.ts
Normal file
32
src/converters/furnituredata/FurnitureDataDownloader.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { singleton } from 'tsyringe';
|
||||
import { Configuration } from '../../common/config/Configuration';
|
||||
import { FileUtilities } from '../../utils/FileUtilities';
|
||||
|
||||
@singleton()
|
||||
export class FurnitureDataDownloader
|
||||
{
|
||||
constructor(private readonly _configuration: Configuration)
|
||||
{}
|
||||
|
||||
public async download(callback: (content: string) => Promise<void>): Promise<void>
|
||||
{
|
||||
const furnitureData = await this.parseFurnitureData();
|
||||
|
||||
if(!furnitureData) throw new Error('invalid_furniture_data');
|
||||
|
||||
callback(furnitureData);
|
||||
}
|
||||
|
||||
public async parseFurnitureData(): Promise<string>
|
||||
{
|
||||
const url = this._configuration.getValue('furnidata.load.url');
|
||||
|
||||
if(!url || !url.length) return null;
|
||||
|
||||
const content = await FileUtilities.readFileAsString(url);
|
||||
|
||||
if(!content || !content.length) return null;
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ 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 { Logger } from '../../utils/Logger';
|
||||
import { PetDownloader } from './PetDownloader';
|
||||
|
||||
@singleton()
|
||||
@ -28,9 +28,7 @@ export class PetConverter extends SWFConverter
|
||||
|
||||
const spinner = ora('Preparing Pets').start();
|
||||
|
||||
const outputFolder = new File(this._configuration.getValue('output.folder.pet'));
|
||||
|
||||
if(!outputFolder.isDirectory()) outputFolder.mkdirs();
|
||||
const directory = this.getDirectory();
|
||||
|
||||
try
|
||||
{
|
||||
@ -43,7 +41,7 @@ export class PetConverter extends SWFConverter
|
||||
const spriteBundle = await this._bundleProvider.generateSpriteSheet(habboAssetSwf);
|
||||
const assetData = await this.mapXML2JSON(habboAssetSwf, 'pet');
|
||||
|
||||
await this.fromHabboAsset(habboAssetSwf, outputFolder.path, 'pet', assetData, spriteBundle);
|
||||
await this.fromHabboAsset(habboAssetSwf, directory.path, 'pet', assetData, spriteBundle);
|
||||
});
|
||||
|
||||
spinner.succeed(`Pets finished in ${ Date.now() - now }ms`);
|
||||
@ -55,35 +53,48 @@ export class PetConverter extends SWFConverter
|
||||
}
|
||||
}
|
||||
|
||||
private getDirectory(): File
|
||||
{
|
||||
const baseFolder = new File(this._configuration.getValue('output.folder'));
|
||||
|
||||
if(!baseFolder.isDirectory()) baseFolder.mkdirs();
|
||||
|
||||
const gameDataFolder = new File(baseFolder.path + 'pet');
|
||||
|
||||
if(!gameDataFolder.isDirectory()) gameDataFolder.mkdirs();
|
||||
|
||||
return gameDataFolder;
|
||||
}
|
||||
|
||||
private async mapXML2JSON(habboAssetSWF: HabboAssetSWF, assetType: string): Promise<IAssetData>
|
||||
{
|
||||
if(!habboAssetSWF) return null;
|
||||
|
||||
const assetData: IAssetData = {};
|
||||
const output: IAssetData = {};
|
||||
|
||||
assetData.type = assetType;
|
||||
output.type = assetType;
|
||||
|
||||
const indexXML = await PetConverter.getIndexXML(habboAssetSWF);
|
||||
|
||||
if(indexXML) IndexMapper.mapXML(indexXML, assetData);
|
||||
if(indexXML) IndexMapper.mapXML(indexXML, output);
|
||||
|
||||
const assetXML = await PetConverter.getAssetsXML(habboAssetSWF);
|
||||
|
||||
if(assetXML)
|
||||
{
|
||||
AssetMapper.mapXML(assetXML, assetData);
|
||||
AssetMapper.mapXML(assetXML, output);
|
||||
|
||||
if(assetData.palettes !== undefined)
|
||||
if(output.palettes !== undefined)
|
||||
{
|
||||
for(const paletteId in assetData.palettes)
|
||||
for(const paletteId in output.palettes)
|
||||
{
|
||||
const palette = assetData.palettes[paletteId];
|
||||
const palette = output.palettes[paletteId];
|
||||
|
||||
const paletteColors = PetConverter.getPalette(habboAssetSWF, palette.source);
|
||||
|
||||
if(!paletteColors)
|
||||
{
|
||||
delete assetData.palettes[paletteId];
|
||||
delete output.palettes[paletteId];
|
||||
|
||||
continue;
|
||||
}
|
||||
@ -99,12 +110,12 @@ export class PetConverter extends SWFConverter
|
||||
|
||||
const logicXML = await PetConverter.getLogicXML(habboAssetSWF);
|
||||
|
||||
if(logicXML) LogicMapper.mapXML(logicXML, assetData);
|
||||
if(logicXML) LogicMapper.mapXML(logicXML, output);
|
||||
|
||||
const visualizationXML = await PetConverter.getVisualizationXML(habboAssetSWF);
|
||||
|
||||
if(visualizationXML) VisualizationMapper.mapXML(visualizationXML, assetData);
|
||||
if(visualizationXML) VisualizationMapper.mapXML(visualizationXML, output);
|
||||
|
||||
return assetData;
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,13 @@ 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';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
@singleton()
|
||||
export class PetDownloader
|
||||
{
|
||||
constructor(
|
||||
private readonly _config: Configuration,
|
||||
private readonly _configuration: Configuration,
|
||||
private readonly _logger: Logger)
|
||||
{}
|
||||
|
||||
@ -34,18 +34,18 @@ export class PetDownloader
|
||||
catch (error)
|
||||
{
|
||||
console.log();
|
||||
console.error(error);
|
||||
console.error(`Error parsing ${ petType }: ` + error.message);
|
||||
|
||||
this._logger.logError(`Error parsing ${ petType }: ` + error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async parsePetTypes(): Promise<string[]>
|
||||
{
|
||||
await this._config.loadExternalVariables();
|
||||
|
||||
const petTypes: string[] = [];
|
||||
|
||||
const pets = this._config.getValue('pet.configuration');
|
||||
const pets = this._configuration.getValue('pet.configuration');
|
||||
|
||||
if(pets)
|
||||
{
|
||||
@ -59,7 +59,7 @@ export class PetDownloader
|
||||
|
||||
public async extractPet(className: string, callback: (habboAssetSwf: HabboAssetSWF) => Promise<void>): Promise<void>
|
||||
{
|
||||
let url = this._config.getValue('dynamic.download.url.pet');
|
||||
let url = this._configuration.getValue('dynamic.download.pet.url');
|
||||
|
||||
if(!url || !url.length) return;
|
||||
|
||||
|
118
src/converters/productdata/ProductDataConverter.ts
Normal file
118
src/converters/productdata/ProductDataConverter.ts
Normal file
@ -0,0 +1,118 @@
|
||||
import { writeFile } from 'fs/promises';
|
||||
import * as ora from 'ora';
|
||||
import { singleton } from 'tsyringe';
|
||||
import { Configuration } from '../../common/config/Configuration';
|
||||
import { Converter } from '../../common/converters/Converter';
|
||||
import { IProductData } from '../../mapping/json';
|
||||
import File from '../../utils/File';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
import { ProductDataDownloader } from './ProductDataDownloader';
|
||||
|
||||
@singleton()
|
||||
export class ProductDataConverter extends Converter
|
||||
{
|
||||
constructor(
|
||||
private readonly _productDataDownloader: ProductDataDownloader,
|
||||
private readonly _configuration: Configuration,
|
||||
private readonly _logger: Logger)
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public async convertAsync(): Promise<void>
|
||||
{
|
||||
const now = Date.now();
|
||||
|
||||
const spinner = ora('Preparing ProductData').start();
|
||||
|
||||
const directory = this.getDirectory();
|
||||
|
||||
try
|
||||
{
|
||||
await this._productDataDownloader.download(async (content: string) =>
|
||||
{
|
||||
spinner.text = 'Parsing FurnitureData';
|
||||
|
||||
spinner.render();
|
||||
|
||||
let productDataString = content;
|
||||
|
||||
if(!productDataString.startsWith('{'))
|
||||
{
|
||||
const productData = await this.mapText2JSON(productDataString);
|
||||
|
||||
productDataString = JSON.stringify(productData);
|
||||
}
|
||||
|
||||
const path = directory.path + '/ProductData.json';
|
||||
|
||||
await writeFile(path, productDataString, 'utf8');
|
||||
});
|
||||
|
||||
spinner.succeed(`ProductData finished in ${ Date.now() - now }ms`);
|
||||
}
|
||||
|
||||
catch (error)
|
||||
{
|
||||
spinner.fail('ProductData failed: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
private getDirectory(): File
|
||||
{
|
||||
const baseFolder = new File(this._configuration.getValue('output.folder'));
|
||||
|
||||
if(!baseFolder.isDirectory()) baseFolder.mkdirs();
|
||||
|
||||
const gameDataFolder = new File(baseFolder.path + '/gamedata');
|
||||
|
||||
if(!gameDataFolder.isDirectory()) gameDataFolder.mkdirs();
|
||||
|
||||
const jsonFolder = new File(gameDataFolder.path + '/json');
|
||||
|
||||
if(!jsonFolder.isDirectory()) jsonFolder.mkdirs();
|
||||
|
||||
return jsonFolder;
|
||||
}
|
||||
|
||||
private async mapText2JSON(text: string): Promise<IProductData>
|
||||
{
|
||||
if(!text) return null;
|
||||
|
||||
const output: IProductData = {
|
||||
productdata: {
|
||||
product: []
|
||||
}
|
||||
};
|
||||
|
||||
text = text.replace(/"{1,}/g, '');
|
||||
|
||||
const parts = text.split(/\n\r{1,}|\n{1,}|\r{1,}/mg);
|
||||
|
||||
for(const part of parts)
|
||||
{
|
||||
const set = part.match(/\[+?((.)*?)\]/g);
|
||||
|
||||
if(set)
|
||||
{
|
||||
for(const entry of set)
|
||||
{
|
||||
let value = entry.replace(/\[{1,}/mg, '');
|
||||
value = entry.replace(/\]{1,}/mg, '');
|
||||
|
||||
value = value.replace('[[', '');
|
||||
value = value.replace('[', '');
|
||||
|
||||
const pieces = value.split(',');
|
||||
const code = pieces.shift();
|
||||
const name = pieces.shift();
|
||||
const description = pieces.join(',');
|
||||
|
||||
output.productdata.product.push({ code, name, description });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
32
src/converters/productdata/ProductDataDownloader.ts
Normal file
32
src/converters/productdata/ProductDataDownloader.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { singleton } from 'tsyringe';
|
||||
import { Configuration } from '../../common/config/Configuration';
|
||||
import { FileUtilities } from '../../utils/FileUtilities';
|
||||
|
||||
@singleton()
|
||||
export class ProductDataDownloader
|
||||
{
|
||||
constructor(private readonly _configuration: Configuration)
|
||||
{}
|
||||
|
||||
public async download(callback: (content: string) => Promise<void>): Promise<void>
|
||||
{
|
||||
const productData = await this.parseProductData();
|
||||
|
||||
if(!productData) throw new Error('invalid_product_data');
|
||||
|
||||
callback(productData);
|
||||
}
|
||||
|
||||
public async parseProductData(): Promise<string>
|
||||
{
|
||||
const url = this._configuration.getValue('productdata.load.url');
|
||||
|
||||
if(!url || !url.length) return null;
|
||||
|
||||
const content = await FileUtilities.readFileAsString(url);
|
||||
|
||||
if(!content || !content.length) return null;
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
@ -2,5 +2,5 @@ import { IEffectMapLibrary } from './IEffectMapLibrary';
|
||||
|
||||
export interface IEffectMap
|
||||
{
|
||||
effects: IEffectMapLibrary[];
|
||||
effects?: IEffectMapLibrary[];
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
export interface IEffectMapLibrary
|
||||
{
|
||||
id: string;
|
||||
lib: string;
|
||||
type: string;
|
||||
revision: number;
|
||||
id?: string;
|
||||
lib?: string;
|
||||
type?: string;
|
||||
revision?: number;
|
||||
}
|
||||
|
@ -2,5 +2,5 @@ import { IFigureMapLibrary } from './IFigureMapLibrary';
|
||||
|
||||
export interface IFigureMap
|
||||
{
|
||||
libraries: IFigureMapLibrary[];
|
||||
libraries?: IFigureMapLibrary[];
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { IFigureMapLibraryPart } from './IFigureMapLibraryPart';
|
||||
|
||||
export interface IFigureMapLibrary
|
||||
{
|
||||
id: string;
|
||||
revision: number;
|
||||
parts: IFigureMapLibraryPart[];
|
||||
id?: string;
|
||||
revision?: number;
|
||||
parts?: IFigureMapLibraryPart[];
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
export interface IFigureMapLibraryPart
|
||||
{
|
||||
id: number;
|
||||
type: string;
|
||||
id?: number;
|
||||
type?: string;
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
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,10 +2,10 @@ import { IFurnitureType } from './IFurnitureType';
|
||||
|
||||
export class IFurnitureData
|
||||
{
|
||||
roomitemtypes: {
|
||||
roomitemtypes?: {
|
||||
furnitype: IFurnitureType[]
|
||||
};
|
||||
wallitemtypes: {
|
||||
wallitemtypes?: {
|
||||
furnitype: IFurnitureType[]
|
||||
};
|
||||
}
|
28
src/mapping/json/furnituredata/IFurnitureType.ts
Normal file
28
src/mapping/json/furnituredata/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;
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
export * from './asset';
|
||||
export * from './effectmap';
|
||||
export * from './figuremap';
|
||||
export * from './furnidata';
|
||||
export * from './furnituredata';
|
||||
export * from './productdata';
|
||||
|
8
src/mapping/json/productdata/IProductData.ts
Normal file
8
src/mapping/json/productdata/IProductData.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { IProductType } from './IProductType';
|
||||
|
||||
export interface IProductData
|
||||
{
|
||||
productdata?: {
|
||||
product: IProductType[]
|
||||
};
|
||||
}
|
6
src/mapping/json/productdata/IProductType.ts
Normal file
6
src/mapping/json/productdata/IProductType.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export interface IProductType
|
||||
{
|
||||
code: string;
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
2
src/mapping/json/productdata/index.ts
Normal file
2
src/mapping/json/productdata/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './IProductData';
|
||||
export * from './IProductType';
|
45
src/mapping/mappers/EffectMapMapper.ts
Normal file
45
src/mapping/mappers/EffectMapMapper.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { IEffectMap, IEffectMapLibrary } from '../json';
|
||||
import { EffectMapEffectXML, EffectMapXML } from '../xml';
|
||||
import { Mapper } from './asset/Mapper';
|
||||
|
||||
export class EffectMapMapper extends Mapper
|
||||
{
|
||||
public static mapXML(xml: any, output: IEffectMap): void
|
||||
{
|
||||
if(!xml || !output) return;
|
||||
|
||||
if(xml.map !== undefined) EffectMapMapper.mapEffectMapXML(new EffectMapXML(xml.map), output);
|
||||
}
|
||||
|
||||
private static mapEffectMapXML(xml: EffectMapXML, output: IEffectMap): void
|
||||
{
|
||||
if(!xml || !output) return;
|
||||
|
||||
if(xml.effects !== undefined)
|
||||
{
|
||||
if(xml.effects.length)
|
||||
{
|
||||
output.effects = [];
|
||||
|
||||
EffectMapMapper.mapEffectMapLibrariesXML(xml.effects, output.effects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static mapEffectMapLibrariesXML(xml: EffectMapEffectXML[], output: IEffectMapLibrary[]): void
|
||||
{
|
||||
if(!xml || !xml.length || !output) return;
|
||||
|
||||
for(const libraryXML of xml)
|
||||
{
|
||||
const library: IEffectMapLibrary = {};
|
||||
|
||||
if(libraryXML.id !== undefined) library.id = libraryXML.id;
|
||||
if(libraryXML.lib !== undefined) library.lib = libraryXML.lib;
|
||||
if(libraryXML.type !== undefined) library.type = libraryXML.type;
|
||||
if(libraryXML.revision !== undefined) library.revision = libraryXML.revision;
|
||||
|
||||
output.push(library);
|
||||
}
|
||||
}
|
||||
}
|
68
src/mapping/mappers/FigureMapMapper.ts
Normal file
68
src/mapping/mappers/FigureMapMapper.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { IFigureMap, IFigureMapLibrary, IFigureMapLibraryPart } from '../json';
|
||||
import { FigureLibraryPartXML, FigureLibraryXML, FigureMapXML } from '../xml';
|
||||
import { Mapper } from './asset/Mapper';
|
||||
|
||||
export class FigureMapMapper extends Mapper
|
||||
{
|
||||
public static mapXML(xml: any, output: IFigureMap): void
|
||||
{
|
||||
if(!xml || !output) return;
|
||||
|
||||
if(xml.map !== undefined) FigureMapMapper.mapFigureMapXML(new FigureMapXML(xml.map), output);
|
||||
}
|
||||
|
||||
private static mapFigureMapXML(xml: FigureMapXML, output: IFigureMap): void
|
||||
{
|
||||
if(!xml || !output) return;
|
||||
|
||||
if(xml.libraries !== undefined)
|
||||
{
|
||||
if(xml.libraries.length)
|
||||
{
|
||||
output.libraries = [];
|
||||
|
||||
FigureMapMapper.mapFigureMapLibrariesXML(xml.libraries, output.libraries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static mapFigureMapLibrariesXML(xml: FigureLibraryXML[], output: IFigureMapLibrary[]): void
|
||||
{
|
||||
if(!xml || !xml.length || !output) return;
|
||||
|
||||
for(const libraryXML of xml)
|
||||
{
|
||||
const library: IFigureMapLibrary = {};
|
||||
|
||||
if(libraryXML.id !== undefined) library.id = libraryXML.id;
|
||||
if(libraryXML.revision !== undefined) library.revision = libraryXML.revision;
|
||||
|
||||
if(libraryXML.parts !== undefined)
|
||||
{
|
||||
if(libraryXML.parts.length)
|
||||
{
|
||||
library.parts = [];
|
||||
|
||||
FigureMapMapper.mapFigureMapLibraryPartsXML(libraryXML.parts, library.parts);
|
||||
}
|
||||
}
|
||||
|
||||
output.push(library);
|
||||
}
|
||||
}
|
||||
|
||||
private static mapFigureMapLibraryPartsXML(xml: FigureLibraryPartXML[], output: IFigureMapLibraryPart[]): void
|
||||
{
|
||||
if(!xml || !xml.length || !output) return;
|
||||
|
||||
for(const libraryPartXML of xml)
|
||||
{
|
||||
const libraryPart: IFigureMapLibraryPart = {};
|
||||
|
||||
if(libraryPartXML.id !== undefined) libraryPart.id = libraryPartXML.id;
|
||||
if(libraryPartXML.type !== undefined) libraryPart.type = libraryPartXML.type;
|
||||
|
||||
output.push(libraryPart);
|
||||
}
|
||||
}
|
||||
}
|
90
src/mapping/mappers/FurnitureDataMapper.ts
Normal file
90
src/mapping/mappers/FurnitureDataMapper.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import { IFurnitureData, IFurnitureType } from '../json';
|
||||
import { FurnitureDataXML, FurnitureTypeXML } from '../xml';
|
||||
import { Mapper } from './asset/Mapper';
|
||||
|
||||
export class FurnitureDataMapper extends Mapper
|
||||
{
|
||||
public static mapXML(xml: any, output: IFurnitureData): void
|
||||
{
|
||||
if(!xml || !output) return;
|
||||
|
||||
if(xml.furnidata !== undefined) FurnitureDataMapper.mapFurnitureDataXML(new FurnitureDataXML(xml.furnidata), output);
|
||||
}
|
||||
|
||||
private static mapFurnitureDataXML(xml: FurnitureDataXML, output: IFurnitureData): void
|
||||
{
|
||||
if(!xml || !output) return;
|
||||
|
||||
if(xml.floorItems !== undefined)
|
||||
{
|
||||
if(xml.floorItems.length)
|
||||
{
|
||||
output.roomitemtypes = {
|
||||
furnitype: []
|
||||
};
|
||||
|
||||
FurnitureDataMapper.mapFurnitureTypesXML(xml.floorItems, output.roomitemtypes.furnitype, 'floor');
|
||||
}
|
||||
}
|
||||
|
||||
if(xml.wallItems !== undefined)
|
||||
{
|
||||
if(xml.wallItems.length)
|
||||
{
|
||||
output.wallitemtypes = {
|
||||
furnitype: []
|
||||
};
|
||||
|
||||
FurnitureDataMapper.mapFurnitureTypesXML(xml.wallItems, output.wallitemtypes.furnitype, 'wall');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static mapFurnitureTypesXML(xml: FurnitureTypeXML[], output: IFurnitureType[], type: string): void
|
||||
{
|
||||
if(!xml || !xml.length || !output) return;
|
||||
|
||||
for(const typeXML of xml)
|
||||
{
|
||||
const furnitureType: IFurnitureType = {};
|
||||
|
||||
furnitureType.id = typeXML.id;
|
||||
furnitureType.classname = typeXML.classname;
|
||||
furnitureType.revision = typeXML.revision;
|
||||
furnitureType.category = typeXML.category;
|
||||
|
||||
if(type === 'floor')
|
||||
{
|
||||
furnitureType.defaultdir = typeXML.defaultdir;
|
||||
furnitureType.xdim = typeXML.xdim;
|
||||
furnitureType.ydim = typeXML.ydim;
|
||||
furnitureType.partcolors = typeXML.partcolors;
|
||||
}
|
||||
|
||||
furnitureType.name = typeXML.name;
|
||||
furnitureType.description = typeXML.description;
|
||||
furnitureType.adurl = typeXML.adurl;
|
||||
furnitureType.offerid = typeXML.offerid;
|
||||
furnitureType.buyout = typeXML.buyout;
|
||||
furnitureType.rentofferid = typeXML.rentofferid;
|
||||
furnitureType.rentbuyout = typeXML.rentbuyout;
|
||||
furnitureType.bc = typeXML.bc;
|
||||
furnitureType.excludeddynamic = typeXML.excludeddynamic;
|
||||
furnitureType.customparams = typeXML.customparams;
|
||||
furnitureType.specialtype = typeXML.specialtype;
|
||||
|
||||
if(type === 'floor')
|
||||
{
|
||||
furnitureType.canstandon = typeXML.canstandon;
|
||||
furnitureType.cansiton = typeXML.cansiton;
|
||||
furnitureType.canlayon = typeXML.canlayon;
|
||||
}
|
||||
|
||||
furnitureType.furniline = typeXML.furniline;
|
||||
furnitureType.environment = typeXML.environment;
|
||||
furnitureType.rare = typeXML.rare;
|
||||
|
||||
output.push(furnitureType);
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +1,4 @@
|
||||
export * from './asset';
|
||||
export * from './EffectMapMapper';
|
||||
export * from './FigureMapMapper';
|
||||
export * from './FurnitureDataMapper';
|
||||
|
@ -1,26 +0,0 @@
|
||||
export class EffectLibraryPartXML
|
||||
{
|
||||
private _id: number;
|
||||
private _type: string;
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes)
|
||||
{
|
||||
if(attributes.id !== undefined) this._id = parseInt(attributes.id);
|
||||
if(attributes.type !== undefined) this._type = attributes.type;
|
||||
}
|
||||
}
|
||||
|
||||
public get id(): number
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get type(): string
|
||||
{
|
||||
return this._type;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
import { EffectLibraryPartXML } from './EffectLibraryPartXML';
|
||||
|
||||
export class EffectLibraryXML
|
||||
{
|
||||
private _id: string;
|
||||
private _revision: number;
|
||||
private _parts: EffectLibraryPartXML[];
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes)
|
||||
{
|
||||
if(attributes.id !== undefined) this._id = attributes.id;
|
||||
if(attributes.revision !== undefined) this._revision = parseInt(attributes.revision);
|
||||
}
|
||||
|
||||
if(xml.part !== undefined)
|
||||
{
|
||||
this._parts = [];
|
||||
|
||||
for(const partId in xml.part)
|
||||
{
|
||||
const part = xml.part[partId];
|
||||
|
||||
this._parts.push(new EffectLibraryPartXML(part));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get id(): string
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get revision(): number
|
||||
{
|
||||
return this._revision;
|
||||
}
|
||||
|
||||
public get parts(): EffectLibraryPartXML[]
|
||||
{
|
||||
return this._parts;
|
||||
}
|
||||
}
|
41
src/mapping/xml/effectmap/EffectMapEffectXML.ts
Normal file
41
src/mapping/xml/effectmap/EffectMapEffectXML.ts
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
export class EffectMapEffectXML
|
||||
{
|
||||
private _id: string;
|
||||
private _lib: string;
|
||||
private _type: string;
|
||||
private _revision: number;
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
const attributes = xml.$;
|
||||
|
||||
if(attributes)
|
||||
{
|
||||
if(attributes.id !== undefined) this._id = attributes.id;
|
||||
if(attributes.lib !== undefined) this._lib = attributes.lib;
|
||||
if(attributes.type !== undefined) this._type = attributes.type;
|
||||
if(attributes.revision !== undefined) this._revision = parseInt(attributes.revision);
|
||||
}
|
||||
}
|
||||
|
||||
public get id(): string
|
||||
{
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get lib(): string
|
||||
{
|
||||
return this._lib;
|
||||
}
|
||||
|
||||
public get type(): string
|
||||
{
|
||||
return this._type;
|
||||
}
|
||||
|
||||
public get revision(): number
|
||||
{
|
||||
return this._revision;
|
||||
}
|
||||
}
|
@ -1,29 +1,24 @@
|
||||
import { EffectLibraryXML } from './EffectLibraryXML';
|
||||
import { EffectMapEffectXML } from './EffectMapEffectXML';
|
||||
|
||||
export class EffectMapXML
|
||||
{
|
||||
private _librares: EffectLibraryXML[];
|
||||
private _effect: EffectMapEffectXML[];
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
if(xml.map !== undefined)
|
||||
if(xml.effect !== undefined)
|
||||
{
|
||||
if(xml.map.lib !== undefined)
|
||||
if(Array.isArray(xml.effect))
|
||||
{
|
||||
this._librares = [];
|
||||
this._effect = [];
|
||||
|
||||
for(const lib in xml.map.lib)
|
||||
{
|
||||
const library = xml.map.lib[lib];
|
||||
|
||||
this._librares.push(new EffectLibraryXML(library));
|
||||
}
|
||||
for(const library of xml.effect) this._effect.push(new EffectMapEffectXML(library));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get libraries(): EffectLibraryXML[]
|
||||
public get effects(): EffectMapEffectXML[]
|
||||
{
|
||||
return this._librares;
|
||||
return this._effect;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,2 @@
|
||||
export * from './EffectLibraryPartXML';
|
||||
export * from './EffectLibraryXML';
|
||||
export * from './EffectMapEffectXML';
|
||||
export * from './EffectMapXML';
|
||||
|
@ -17,6 +17,8 @@ export class FigureLibraryXML
|
||||
}
|
||||
|
||||
if(xml.part !== undefined)
|
||||
{
|
||||
if(Array.isArray(xml.part))
|
||||
{
|
||||
this._parts = [];
|
||||
|
||||
@ -28,6 +30,7 @@ export class FigureLibraryXML
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get id(): string
|
||||
{
|
||||
|
@ -6,15 +6,15 @@ export class FigureMapXML
|
||||
|
||||
constructor(xml: any)
|
||||
{
|
||||
if(xml.map !== undefined)
|
||||
if(xml.lib !== undefined)
|
||||
{
|
||||
if(xml.map.lib !== undefined)
|
||||
if(Array.isArray(xml.lib))
|
||||
{
|
||||
this._librares = [];
|
||||
|
||||
for(const lib in xml.map.lib)
|
||||
for(const lib in xml.lib)
|
||||
{
|
||||
const library = xml.map.lib[lib];
|
||||
const library = xml.lib[lib];
|
||||
|
||||
this._librares.push(new FigureLibraryXML(library));
|
||||
}
|
||||
|
@ -13,13 +13,13 @@ export class FurnitureDataXML
|
||||
{
|
||||
this._floorItems = [];
|
||||
|
||||
for(const roomitemtype in xml.roomitemtypes)
|
||||
for(const roomitemtype of xml.roomitemtypes)
|
||||
{
|
||||
const furniTypes = xml.roomitemtypes[roomitemtype];
|
||||
const furniTypes = roomitemtype.furnitype;
|
||||
|
||||
if(furniTypes !== undefined)
|
||||
{
|
||||
for(const furniType in furniTypes) this._floorItems.push(new FurnitureTypeXML('floor', furniType));
|
||||
if(Array.isArray(furniTypes)) for(const furniType of furniTypes) this._floorItems.push(new FurnitureTypeXML('floor', furniType));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -28,13 +28,13 @@ export class FurnitureDataXML
|
||||
{
|
||||
this._wallItems = [];
|
||||
|
||||
for(const wallitemtype in xml.wallitemtypes)
|
||||
for(const wallitemtype of xml.wallitemtypes)
|
||||
{
|
||||
const furniTypes = xml.wallitemtypes[wallitemtype];
|
||||
const furniTypes = wallitemtype.furnitype;
|
||||
|
||||
if(furniTypes !== undefined)
|
||||
{
|
||||
for(const furniType in furniTypes) this._wallItems.push(new FurnitureTypeXML('wall', furniType));
|
||||
if(Array.isArray(furniTypes)) for(const furniType in furniTypes) this._wallItems.push(new FurnitureTypeXML('wall', furniType));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
export * from './asset';
|
||||
export * from './effectmap';
|
||||
export * from './figuremap';
|
||||
export * from './furnidata';
|
||||
export * from './furnituredata';
|
||||
|
@ -12,6 +12,8 @@ export class FileUtilities
|
||||
|
||||
let content: Buffer = null;
|
||||
|
||||
if(url.startsWith('//')) url = ('https:' + url);
|
||||
|
||||
if(url.startsWith('http'))
|
||||
{
|
||||
const data = await fetch.default(url);
|
||||
@ -33,6 +35,8 @@ export class FileUtilities
|
||||
|
||||
let content = null;
|
||||
|
||||
if(url.startsWith('//')) url = ('https:' + url);
|
||||
|
||||
if(url.startsWith('http'))
|
||||
{
|
||||
const data = await fetch.default(url);
|
||||
|
@ -1,22 +1,19 @@
|
||||
import { createWriteStream, existsSync } from 'fs';
|
||||
import { appendFile } from 'fs/promises';
|
||||
import { WriteStream } from 'fs';
|
||||
import { singleton } from 'tsyringe';
|
||||
|
||||
@singleton()
|
||||
export default class Logger
|
||||
export class Logger
|
||||
{
|
||||
private _fileName: string = `error-${ Date.now() }.log`;
|
||||
private _writeStream: WriteStream = null;
|
||||
|
||||
constructor()
|
||||
{
|
||||
if(!existsSync('error.log'))
|
||||
{
|
||||
const createStream = createWriteStream('error.log');
|
||||
createStream.end();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public logErrorAsync(message: string): Promise<void>
|
||||
public logError(message: string): void
|
||||
{
|
||||
return appendFile('error.log', message + '\n');
|
||||
//
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user