mirror of
https://github.com/billsonnn/nitro-converter.git
synced 2024-11-22 15:40:52 +01:00
Change everything
This commit is contained in:
parent
342fa7f122
commit
73fe879160
2
.gitignore
vendored
2
.gitignore
vendored
@ -50,6 +50,8 @@ Thumbs.db
|
||||
*.zip
|
||||
*.as
|
||||
*.bin
|
||||
.env
|
||||
assets/
|
||||
|
||||
# Nitro
|
||||
/src/configuration.json
|
||||
|
4679
package-lock.json
generated
4679
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "ts-node-transpile-only src/Main.ts",
|
||||
"start": "node dist/Main.js",
|
||||
"start:dev": "ts-node-dev --respawn --transpile-only src/Main.ts"
|
||||
},
|
||||
"author": "",
|
||||
@ -20,8 +20,10 @@
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-gzip": "^1.1.2",
|
||||
"ora": "^5.3.0",
|
||||
"pako": "^2.0.4",
|
||||
"png-stream": "^1.0.5",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"shelljs": "^0.8.4",
|
||||
"stream-to-array": "^2.3.0",
|
||||
"tsyringe": "^4.4.0",
|
||||
"xml2js": "^0.4.23"
|
||||
@ -30,6 +32,9 @@
|
||||
"@types/bytebuffer": "^5.0.42",
|
||||
"@types/node": "^14.14.28",
|
||||
"@types/node-fetch": "^2.5.8",
|
||||
"@types/pako": "^1.0.2",
|
||||
"@types/shelljs": "^0.8.10",
|
||||
"@types/stream-to-array": "^2.3.0",
|
||||
"@types/xml2js": "^0.4.8",
|
||||
"@typescript-eslint/eslint-plugin": "^4.15.1",
|
||||
"@typescript-eslint/parser": "^4.15.1",
|
||||
|
22
src/Main.ts
22
src/Main.ts
@ -10,14 +10,11 @@ import { FigureDataConverter } from './converters/FigureDataConverter';
|
||||
import { FigureMapConverter } from './converters/FigureMapConverter';
|
||||
import { FurnitureConverter } from './converters/FurnitureConverter';
|
||||
import { FurnitureDataConverter } from './converters/FurnitureDataConverter';
|
||||
import { OldAssetConverter } from './converters/OldAssetConverter';
|
||||
import { PetConverter } from './converters/PetConverter';
|
||||
import { ProductDataConverter } from './converters/ProductDataConverter';
|
||||
|
||||
(async () =>
|
||||
{
|
||||
checkNodeVersion();
|
||||
|
||||
const config = container.resolve(Configuration);
|
||||
await config.init();
|
||||
|
||||
@ -31,26 +28,15 @@ import { ProductDataConverter } from './converters/ProductDataConverter';
|
||||
FurnitureConverter,
|
||||
FigureConverter,
|
||||
EffectConverter,
|
||||
PetConverter,
|
||||
OldAssetConverter
|
||||
PetConverter
|
||||
];
|
||||
|
||||
const [ arg1, arg2, ...rest ] = process.argv;
|
||||
|
||||
for(const converterClass of converters)
|
||||
{
|
||||
const converter = (container.resolve<any>(converterClass) as IConverter);
|
||||
|
||||
await converter.convertAsync(rest);
|
||||
await converter.convertAsync();
|
||||
}
|
||||
})();
|
||||
|
||||
function checkNodeVersion()
|
||||
{
|
||||
const version = process.version.replace('v', '');
|
||||
const major = version.split('.')[0];
|
||||
if(parseInt(major) < 14)
|
||||
{
|
||||
throw new Error('Invalid node version: ' + version + ' please use >= 14');
|
||||
}
|
||||
}
|
||||
process.kill(process.pid, 'SIGTERM');
|
||||
})();
|
||||
|
@ -1,104 +0,0 @@
|
||||
import { packAsync } from 'free-tex-packer-core';
|
||||
import { HabboAssetSWF } from '../../swf/HabboAssetSWF';
|
||||
import { ImageBundle } from './ImageBundle';
|
||||
import { SpriteBundle } from './SpriteBundle';
|
||||
|
||||
export class BundleProvider
|
||||
{
|
||||
public static imageSource: Map<string, string> = new Map();
|
||||
|
||||
public static async generateSpriteSheet(habboAssetSWF: HabboAssetSWF, convertCase: boolean = false): Promise<SpriteBundle>
|
||||
{
|
||||
const tagList = habboAssetSWF.symbolTags();
|
||||
const names: string[] = [];
|
||||
const tags: number[] = [];
|
||||
|
||||
let documentClass = habboAssetSWF.getDocumentClass();
|
||||
|
||||
if(convertCase) documentClass = (documentClass.replace(/(?:^|\.?)([A-Z])/g, (x,y) => ('_' + y.toLowerCase().replace(/^_/, ''))));
|
||||
|
||||
for(const tag of tagList)
|
||||
{
|
||||
names.push(...tag.names);
|
||||
tags.push(...tag.tags);
|
||||
}
|
||||
|
||||
const imageBundle = new ImageBundle();
|
||||
|
||||
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;
|
||||
|
||||
if(imageTag.className.startsWith('sh_')) continue;
|
||||
|
||||
if(imageTag.className.indexOf('_32_') >= 0) continue;
|
||||
|
||||
BundleProvider.imageSource.set(names[i].substring(documentClass.length + 1), imageTag.className.substring(documentClass.length + 1));
|
||||
}
|
||||
}
|
||||
|
||||
if(imageTag.className.startsWith('sh_')) continue;
|
||||
|
||||
if(imageTag.className.indexOf('_32_') >= 0) continue;
|
||||
|
||||
let className = imageTag.className;
|
||||
|
||||
if(convertCase) className = ((className.replace(/(?:^|\.?)([A-Z])/g, (x,y) => ('_' + y.toLowerCase().replace(/^_/, '')))).substring(1));
|
||||
|
||||
imageBundle.addImage(className, imageTag.imgData);
|
||||
}
|
||||
|
||||
if(!imageBundle.images.length) return null;
|
||||
|
||||
return await this.packImages(documentClass, imageBundle, convertCase);
|
||||
}
|
||||
|
||||
private static async packImages(documentClass: string, imageBundle: ImageBundle, convertCase: boolean = false): Promise<SpriteBundle>
|
||||
{
|
||||
const files = await packAsync(imageBundle.images, {
|
||||
textureName: (convertCase ? documentClass.substring(1) : documentClass),
|
||||
width: 10240,
|
||||
height: 4320,
|
||||
fixedSize: false,
|
||||
allowRotation: false,
|
||||
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(convertCase) bundle.imageData.name = (documentClass.replace(/(?:^|\.?)([A-Z])/g, (x,y) => ('_' + y.toLowerCase().replace(/^_/, '')))).substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
if((bundle.spritesheet !== undefined) && (bundle.imageData !== undefined)) bundle.spritesheet.meta.image = bundle.imageData.name;
|
||||
|
||||
return bundle;
|
||||
}
|
||||
}
|
75
src/common/bundle/NitroBundle.ts
Normal file
75
src/common/bundle/NitroBundle.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import ByteBuffer from 'bytebuffer';
|
||||
import { Data, deflate, inflate } from 'pako';
|
||||
import { BinaryReader } from '../utils';
|
||||
|
||||
export class NitroBundle
|
||||
{
|
||||
private readonly _files: Map<string, Buffer>;
|
||||
|
||||
constructor()
|
||||
{
|
||||
this._files = new Map<string, Buffer>();
|
||||
}
|
||||
|
||||
public static from(buffer: ArrayBuffer): NitroBundle
|
||||
{
|
||||
const nitroBundle = new NitroBundle();
|
||||
const binaryReader = new BinaryReader(buffer);
|
||||
|
||||
let fileCount = binaryReader.readShort();
|
||||
|
||||
while(fileCount > 0)
|
||||
{
|
||||
const fileNameLength = binaryReader.readShort();
|
||||
const fileName = binaryReader.readBytes(fileNameLength).toString();
|
||||
const fileLength = binaryReader.readInt();
|
||||
const buffer = binaryReader.readBytes(fileLength);
|
||||
const decompressed = inflate((buffer.toArrayBuffer() as Data));
|
||||
|
||||
nitroBundle.addFile(fileName, Buffer.from(decompressed.buffer));
|
||||
|
||||
fileCount--;
|
||||
}
|
||||
|
||||
return nitroBundle;
|
||||
}
|
||||
|
||||
public addFile(name: string, data: Buffer): void
|
||||
{
|
||||
this._files.set(name, data);
|
||||
}
|
||||
|
||||
public async toBufferAsync(): Promise<Buffer>
|
||||
{
|
||||
const buffer = new ByteBuffer();
|
||||
|
||||
buffer.writeUint16(this._files.size);
|
||||
|
||||
for(const file of this._files.entries())
|
||||
{
|
||||
const fileName = file[0];
|
||||
const fileBuffer = file[1];
|
||||
|
||||
buffer.writeUint16(fileName.length);
|
||||
buffer.writeString(fileName);
|
||||
|
||||
const compressed = deflate(fileBuffer);
|
||||
buffer.writeUint32(compressed.length);
|
||||
buffer.append(compressed);
|
||||
}
|
||||
|
||||
buffer.flip();
|
||||
|
||||
return buffer.toBuffer();
|
||||
}
|
||||
|
||||
public get files(): Map<string, Buffer>
|
||||
{
|
||||
return this._files;
|
||||
}
|
||||
|
||||
public get totalFiles(): number
|
||||
{
|
||||
return this._files.size;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { ISpritesheetData } from '../../mapping/json';
|
||||
import { ISpritesheetData } from '../mapping';
|
||||
|
||||
export class SpriteBundle
|
||||
{
|
||||
|
3
src/common/bundle/index.ts
Normal file
3
src/common/bundle/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './ImageBundle';
|
||||
export * from './NitroBundle';
|
||||
export * from './SpriteBundle';
|
@ -1,6 +1,6 @@
|
||||
import { singleton } from 'tsyringe';
|
||||
import * as configuration from '../../configuration.json';
|
||||
import { FileUtilities } from '../../utils/FileUtilities';
|
||||
import { FileUtilities } from '../utils';
|
||||
|
||||
@singleton()
|
||||
export class Configuration
|
||||
@ -101,6 +101,7 @@ export class Configuration
|
||||
|
||||
public interpolate(value: string, regex: RegExp = null): string
|
||||
{
|
||||
if(!value || (typeof value === 'object')) return value;
|
||||
if(!regex) regex = new RegExp(/\${(.*?)}/g);
|
||||
|
||||
const pieces = value.match(regex);
|
||||
|
1
src/common/config/index.ts
Normal file
1
src/common/config/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './Configuration';
|
@ -1,9 +0,0 @@
|
||||
import { IConverter } from './IConverter';
|
||||
|
||||
export class Converter implements IConverter
|
||||
{
|
||||
public async convertAsync(args: string[] = []): Promise<void>
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
7
src/common/converters/ConverterResult.ts
Normal file
7
src/common/converters/ConverterResult.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export class ConverterResult
|
||||
{
|
||||
public static OK: number = 1;
|
||||
public static BAD_ARGS: number = 2;
|
||||
public static FILE_EXISTS: number = 3;
|
||||
public static INVALID_SWF: number = 4;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
export class ConverterType
|
||||
{
|
||||
public static EFFECT_CONVERTER: string = 'effect';
|
||||
public static FIGURE_CONVERTER: string = 'figure';
|
||||
public static FURNITURE_CONVERTER: string = 'furni';
|
||||
public static PET_CONVERTER: string = 'pet';
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
export interface IConverter
|
||||
{
|
||||
convertAsync(args?: string[]): Promise<void>;
|
||||
convertAsync(): Promise<void>;
|
||||
}
|
||||
|
2
src/common/converters/index.ts
Normal file
2
src/common/converters/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './ConverterResult';
|
||||
export * from './IConverter';
|
40
src/common/index.ts
Normal file
40
src/common/index.ts
Normal file
@ -0,0 +1,40 @@
|
||||
export * from './bundle';
|
||||
export * from './config';
|
||||
export * from './converters';
|
||||
export * from './mapping';
|
||||
export * from './mapping/json';
|
||||
export * from './mapping/json/asset';
|
||||
export * from './mapping/json/asset/animation';
|
||||
export * from './mapping/json/asset/logic';
|
||||
export * from './mapping/json/asset/logic/model';
|
||||
export * from './mapping/json/asset/logic/particlesystem';
|
||||
export * from './mapping/json/asset/spritesheet';
|
||||
export * from './mapping/json/asset/visualization';
|
||||
export * from './mapping/json/asset/visualization/animation';
|
||||
export * from './mapping/json/asset/visualization/color';
|
||||
export * from './mapping/json/asset/visualization/gestures';
|
||||
export * from './mapping/json/asset/visualization/postures';
|
||||
export * from './mapping/json/effectmap';
|
||||
export * from './mapping/json/externaltexts';
|
||||
export * from './mapping/json/figuredata';
|
||||
export * from './mapping/json/figuremap';
|
||||
export * from './mapping/json/furnituredata';
|
||||
export * from './mapping/json/productdata';
|
||||
export * from './mapping/mappers';
|
||||
export * from './mapping/mappers/asset';
|
||||
export * from './mapping/xml';
|
||||
export * from './mapping/xml/asset';
|
||||
export * from './mapping/xml/asset/animation';
|
||||
export * from './mapping/xml/asset/assets';
|
||||
export * from './mapping/xml/asset/logic';
|
||||
export * from './mapping/xml/asset/logic/model';
|
||||
export * from './mapping/xml/asset/logic/particlesystem';
|
||||
export * from './mapping/xml/asset/manifest';
|
||||
export * from './mapping/xml/asset/visualization';
|
||||
export * from './mapping/xml/asset/visualization/animation';
|
||||
export * from './mapping/xml/asset/visualization/color';
|
||||
export * from './mapping/xml/effectmap';
|
||||
export * from './mapping/xml/figuredata';
|
||||
export * from './mapping/xml/figuremap';
|
||||
export * from './mapping/xml/furnituredata';
|
||||
export * from './utils';
|
35
src/common/mapping/index.ts
Normal file
35
src/common/mapping/index.ts
Normal file
@ -0,0 +1,35 @@
|
||||
export * from './json';
|
||||
export * from './json/asset';
|
||||
export * from './json/asset/animation';
|
||||
export * from './json/asset/logic';
|
||||
export * from './json/asset/logic/model';
|
||||
export * from './json/asset/logic/particlesystem';
|
||||
export * from './json/asset/spritesheet';
|
||||
export * from './json/asset/visualization';
|
||||
export * from './json/asset/visualization/animation';
|
||||
export * from './json/asset/visualization/color';
|
||||
export * from './json/asset/visualization/gestures';
|
||||
export * from './json/asset/visualization/postures';
|
||||
export * from './json/effectmap';
|
||||
export * from './json/externaltexts';
|
||||
export * from './json/figuredata';
|
||||
export * from './json/figuremap';
|
||||
export * from './json/furnituredata';
|
||||
export * from './json/productdata';
|
||||
export * from './mappers';
|
||||
export * from './mappers/asset';
|
||||
export * from './xml';
|
||||
export * from './xml/asset';
|
||||
export * from './xml/asset/animation';
|
||||
export * from './xml/asset/assets';
|
||||
export * from './xml/asset/logic';
|
||||
export * from './xml/asset/logic/model';
|
||||
export * from './xml/asset/logic/particlesystem';
|
||||
export * from './xml/asset/manifest';
|
||||
export * from './xml/asset/visualization';
|
||||
export * from './xml/asset/visualization/animation';
|
||||
export * from './xml/asset/visualization/color';
|
||||
export * from './xml/effectmap';
|
||||
export * from './xml/figuredata';
|
||||
export * from './xml/figuremap';
|
||||
export * from './xml/furnituredata';
|
@ -3,4 +3,5 @@ export interface IAssetDimension
|
||||
x: number;
|
||||
y: number;
|
||||
z?: number;
|
||||
}
|
||||
centerZ?: number;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { IEffectMap, IEffectMapLibrary } from '../json';
|
||||
import { EffectMapEffectXML, EffectMapXML } from '../xml';
|
||||
import { Mapper } from './asset/Mapper';
|
||||
import { Mapper } from './asset';
|
||||
|
||||
export class EffectMapMapper extends Mapper
|
||||
{
|
@ -1,18 +1,6 @@
|
||||
import { IFigureDataHiddenLayer } from '../json';
|
||||
import { IFigureDataPalette } from '../json/figuredata/IFigureDataPalette';
|
||||
import { IFigureDataSet } from '../json/figuredata/IFigureDataSet';
|
||||
import { FigureDataHiddenLayerXML } from '../xml';
|
||||
import { FigureDataColorXML } from '../xml/figuredata/FigureDataColorXML';
|
||||
import { FigureDataPaletteXML } from '../xml/figuredata/FigureDataPaletteXML';
|
||||
import { FigureDataXML } from '../xml/figuredata/FigureDataXML';
|
||||
import { IFigureData } from './../json/figuredata/IFigureData';
|
||||
import { IFigureDataColor } from './../json/figuredata/IFigureDataColor';
|
||||
import { IFigureDataPart } from './../json/figuredata/IFigureDataPart';
|
||||
import { IFigureDataSetType } from './../json/figuredata/IFigureDataSetType';
|
||||
import { FigureDataPartXML } from './../xml/figuredata/FigureDataPartXML';
|
||||
import { FigureDataSetTypeXML } from './../xml/figuredata/FigureDataSetTypeXML';
|
||||
import { FigureDataSetXML } from './../xml/figuredata/FigureDataSetXML';
|
||||
import { Mapper } from './asset/Mapper';
|
||||
import { IFigureData, IFigureDataColor, IFigureDataHiddenLayer, IFigureDataPalette, IFigureDataPart, IFigureDataSet, IFigureDataSetType } from '../json';
|
||||
import { FigureDataColorXML, FigureDataHiddenLayerXML, FigureDataPaletteXML, FigureDataPartXML, FigureDataSetTypeXML, FigureDataSetXML, FigureDataXML } from '../xml';
|
||||
import { Mapper } from './asset';
|
||||
|
||||
export class FigureDataMapper extends Mapper
|
||||
{
|
@ -1,6 +1,6 @@
|
||||
import { IFigureMap, IFigureMapLibrary, IFigureMapLibraryPart } from '../json';
|
||||
import { FigureLibraryPartXML, FigureLibraryXML, FigureMapXML } from '../xml';
|
||||
import { Mapper } from './asset/Mapper';
|
||||
import { Mapper } from './asset';
|
||||
|
||||
export class FigureMapMapper extends Mapper
|
||||
{
|
@ -1,6 +1,6 @@
|
||||
import { IFurnitureData, IFurnitureType } from '../json';
|
||||
import { FurnitureDataXML, FurnitureTypeXML } from '../xml';
|
||||
import { Mapper } from './asset/Mapper';
|
||||
import { Mapper } from './asset';
|
||||
|
||||
export class FurnitureDataMapper extends Mapper
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
import { BundleProvider } from '../../../common/bundle/BundleProvider';
|
||||
import { IMAGE_SOURCES } from '../../../../swf';
|
||||
import { IAsset, IAssetData, IAssetPalette } from '../../json';
|
||||
import { AssetsXML, AssetXML, PaletteXML } from '../../xml';
|
||||
import { Mapper } from './Mapper';
|
||||
@ -55,12 +55,12 @@ export class AssetMapper extends Mapper
|
||||
{
|
||||
asset.source = assetXML.source;
|
||||
|
||||
if(BundleProvider.imageSource.has(assetXML.source)) asset.source = BundleProvider.imageSource.get(assetXML.source) as string;
|
||||
if(IMAGE_SOURCES.has(assetXML.source)) asset.source = IMAGE_SOURCES.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(IMAGE_SOURCES.has(assetXML.name)) asset.source = IMAGE_SOURCES.get(assetXML.name) as string;
|
||||
}
|
||||
|
||||
if(assetXML.x !== undefined) asset.x = assetXML.x;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user