Add external texts converter

This commit is contained in:
Bill 2021-02-22 00:39:02 -05:00
parent c54fddd5ea
commit 7b463ab250
18 changed files with 182 additions and 48 deletions

View File

@ -1,10 +1,10 @@
{ {
"name": "nitroassetconverter", "name": "nitro-converter",
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"start:dev": "ts-node-dev --respawn --transpile-only src/Main.ts" "start:dev": "ts-node-dev --respawn --transpile-only src/main.ts"
}, },
"author": "", "author": "",
"license": "ISC", "license": "ISC",

View File

@ -1,8 +1,10 @@
import 'reflect-metadata'; import 'reflect-metadata';
import { container } from 'tsyringe'; import { container } from 'tsyringe';
import { Configuration } from './common/config/Configuration'; import { Configuration } from './common/config/Configuration';
import { IConverter } from './common/converters/IConverter';
import { EffectConverter } from './converters/effect/EffectConverter'; import { EffectConverter } from './converters/effect/EffectConverter';
import { EffectMapConverter } from './converters/effectmap/EffectMapConverter'; import { EffectMapConverter } from './converters/effectmap/EffectMapConverter';
import { ExternalTextsConverter } from './converters/externaltexts/ExternalTextsConverter';
import { FigureConverter } from './converters/figure/FigureConverter'; import { FigureConverter } from './converters/figure/FigureConverter';
import { FigureMapConverter } from './converters/figuremap/FigureMapConverter'; import { FigureMapConverter } from './converters/figuremap/FigureMapConverter';
import { FurnitureConverter } from './converters/furniture/FurnitureConverter'; import { FurnitureConverter } from './converters/furniture/FurnitureConverter';
@ -15,51 +17,22 @@ import { ProductDataConverter } from './converters/productdata/ProductDataConver
const config = container.resolve(Configuration); const config = container.resolve(Configuration);
await config.init(); await config.init();
if(config.getBoolean('convert.figuremap')) const converters = [
{ FigureMapConverter,
const figureMapConverter = container.resolve(FigureMapConverter); EffectMapConverter,
await figureMapConverter.convertAsync(); FurnitureDataConverter,
} ProductDataConverter,
ExternalTextsConverter,
FigureConverter,
EffectConverter,
FurnitureConverter,
PetConverter
];
if(config.getBoolean('convert.effectmap')) for(const converterClass of converters)
{ {
const effectMapConverter = container.resolve(EffectMapConverter); const converter = (container.resolve<any>(converterClass) as IConverter);
await effectMapConverter.convertAsync();
}
if(config.getBoolean('convert.furnidata')) await converter.convertAsync();
{
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);
await furnitureConverter.convertAsync();
}
if(config.getBoolean('convert.pet'))
{
const petConverter = container.resolve(PetConverter);
await petConverter.convertAsync();
} }
})(); })();

View File

@ -1,4 +1,9 @@
export class Converter import { IConverter } from './IConverter';
{
export class Converter implements IConverter
{
public async convertAsync(): Promise<void>
{
return;
}
} }

View File

@ -0,0 +1,4 @@
export interface IConverter
{
convertAsync(): Promise<void>;
}

View File

@ -11,7 +11,8 @@
"flash.dynamic.download.url": "", "flash.dynamic.download.url": "",
"dynamic.download.furniture.url": "${flash.dynamic.download.url}%revision%/%className%.swf", "dynamic.download.furniture.url": "${flash.dynamic.download.url}%revision%/%className%.swf",
"external.variables.url": "https://www.habbo.com/gamedata/external_variables/1", "external.variables.url": "https://www.habbo.com/gamedata/external_variables/1",
"convert.furnidata": "1", "external.texts.url": "${external.texts.txt}",
"convert.furnituredata": "1",
"convert.productdata": "1", "convert.productdata": "1",
"convert.figuremap": "1", "convert.figuremap": "1",
"convert.effectmap": "1", "convert.effectmap": "1",

View File

@ -24,6 +24,8 @@ export class EffectConverter extends SWFConverter
public async convertAsync(): Promise<void> public async convertAsync(): Promise<void>
{ {
if(!this._configuration.getBoolean('convert.effect')) return;
const now = Date.now(); const now = Date.now();
const spinner = ora('Preparing Effects').start(); const spinner = ora('Preparing Effects').start();

View File

@ -23,6 +23,8 @@ export class EffectMapConverter extends Converter
public async convertAsync(): Promise<void> public async convertAsync(): Promise<void>
{ {
if(!this._configuration.getBoolean('convert.effectmap')) return;
const now = Date.now(); const now = Date.now();
const spinner = ora('Preparing EffectMap').start(); const spinner = ora('Preparing EffectMap').start();

View File

@ -0,0 +1,97 @@
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 { IExternalTexts } from '../../mapping/json';
import File from '../../utils/File';
import { Logger } from '../../utils/Logger';
import { ExternalTextsDownloader } from './ExternalTextsDownloader';
@singleton()
export class ExternalTextsConverter extends Converter
{
constructor(
private readonly _externalTextsDownloader: ExternalTextsDownloader,
private readonly _configuration: Configuration,
private readonly _logger: Logger)
{
super();
}
public async convertAsync(): Promise<void>
{
if(!this._configuration.getBoolean('convert.externaltexts')) return;
const now = Date.now();
const spinner = ora('Preparing ExternalTexts').start();
const directory = this.getDirectory();
try
{
await this._externalTextsDownloader.download(async (content: string) =>
{
spinner.text = 'Parsing ExternalTexts';
spinner.render();
let externalTextsString = content;
if(!externalTextsString.startsWith('{'))
{
const externalTexts = await this.mapText2JSON(externalTextsString);
externalTextsString = JSON.stringify(externalTexts);
}
const path = directory.path + '/ExternalTexts.json';
await writeFile(path, externalTextsString, 'utf8');
});
spinner.succeed(`ExternalTexts finished in ${ Date.now() - now }ms`);
}
catch (error)
{
spinner.fail('ExternalTexts 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<IExternalTexts>
{
if(!text) return null;
const output: IExternalTexts = {};
const parts = text.split(/\n\r{1,}|\n{1,}|\r{1,}/mg);
for(const part of parts)
{
const [ key, value ] = part.split('=');
output[key] = value;
}
return output;
}
}

View File

@ -0,0 +1,32 @@
import { singleton } from 'tsyringe';
import { Configuration } from '../../common/config/Configuration';
import { FileUtilities } from '../../utils/FileUtilities';
@singleton()
export class ExternalTextsDownloader
{
constructor(private readonly _configuration: Configuration)
{}
public async download(callback: (content: string) => Promise<void>): Promise<void>
{
const productData = await this.parseExternalTexts();
if(!productData) throw new Error('invalid_external_texts');
callback(productData);
}
public async parseExternalTexts(): Promise<string>
{
const url = this._configuration.getValue('external.texts.url');
if(!url || !url.length) return null;
const content = await FileUtilities.readFileAsString(url);
if(!content || !content.length) return null;
return content;
}
}

View File

@ -24,6 +24,8 @@ export class FigureConverter extends SWFConverter
public async convertAsync(): Promise<void> public async convertAsync(): Promise<void>
{ {
if(!this._configuration.getBoolean('convert.figure')) return;
const now = Date.now(); const now = Date.now();
const spinner = ora('Preparing Figure').start(); const spinner = ora('Preparing Figure').start();

View File

@ -23,6 +23,8 @@ export class FigureMapConverter extends Converter
public async convertAsync(): Promise<void> public async convertAsync(): Promise<void>
{ {
if(!this._configuration.getBoolean('convert.figuremap')) return;
const now = Date.now(); const now = Date.now();
const spinner = ora('Preparing FigureMap').start(); const spinner = ora('Preparing FigureMap').start();

View File

@ -24,6 +24,8 @@ export class FurnitureConverter extends SWFConverter
public async convertAsync(): Promise<void> public async convertAsync(): Promise<void>
{ {
if(!this._configuration.getBoolean('convert.furniture')) return;
const now = Date.now(); const now = Date.now();
const spinner = ora('Preparing Furniture').start(); const spinner = ora('Preparing Furniture').start();

View File

@ -23,6 +23,8 @@ export class FurnitureDataConverter extends Converter
public async convertAsync(): Promise<void> public async convertAsync(): Promise<void>
{ {
if(!this._configuration.getBoolean('convert.furnituredata')) return;
const now = Date.now(); const now = Date.now();
const spinner = ora('Preparing FurnitureData').start(); const spinner = ora('Preparing FurnitureData').start();

View File

@ -24,6 +24,8 @@ export class PetConverter extends SWFConverter
public async convertAsync(): Promise<void> public async convertAsync(): Promise<void>
{ {
if(!this._configuration.getBoolean('convert.pet')) return;
const now = Date.now(); const now = Date.now();
const spinner = ora('Preparing Pets').start(); const spinner = ora('Preparing Pets').start();

View File

@ -21,6 +21,8 @@ export class ProductDataConverter extends Converter
public async convertAsync(): Promise<void> public async convertAsync(): Promise<void>
{ {
if(!this._configuration.getBoolean('convert.productdata')) return;
const now = Date.now(); const now = Date.now();
const spinner = ora('Preparing ProductData').start(); const spinner = ora('Preparing ProductData').start();

View File

@ -0,0 +1,4 @@
export interface IExternalTexts
{
[index: string]: string
}

View File

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

View File

@ -1,5 +1,6 @@
export * from './asset'; export * from './asset';
export * from './effectmap'; export * from './effectmap';
export * from './externaltexts';
export * from './figuremap'; export * from './figuremap';
export * from './furnituredata'; export * from './furnituredata';
export * from './productdata'; export * from './productdata';