adofai-decoration-optimizer/wowsans.js

73 lines
1.8 KiB
JavaScript

import { copyFile, mkdir, readFile, readdir, rm, writeFile } from 'fs/promises'
import yargs from 'yargs'
import { parseADOFAILevel } from './parser.js'
import { basename, dirname, join } from 'path'
import { existsSync } from 'fs'
import sharp from 'sharp'
const args = yargs(process.argv)
const path = args.argv._[2]
const ratio = Number(args.argv._[3])
if (isNaN(ratio)) throw new Error('ratio is not number')
console.log(path)
const file = await readFile(path)
const level = parseADOFAILevel(file)
const workDir = join(process.cwd(), 'work')
if (existsSync(workDir)) await rm(workDir, { recursive: true, force: true })
await mkdir(workDir)
const origLevelDir = dirname(path)
for (const item of await readdir(origLevelDir)) {
await copyFile(join(origLevelDir, item), join(workDir, item))
}
const decoFiles = new Set()
const textTags = new Set()
for (const deco of level.decorations) {
if (deco.eventType === 'AddDecoration') {
deco.scale = deco.scale.map((x) => x / ratio)
decoFiles.add(deco.decorationImage)
} else if (deco.eventType === 'AddText') {
textTags.add(deco.tag)
}
}
for (const action of level.actions) {
if (action.eventType === 'MoveDecorations') {
if (textTags.has(action.tag)) continue
if (action.scale) action.scale = action.scale.map((x) => x / ratio)
if (action.decorationImage) decoFiles.add(action.decorationImage)
}
}
for (const f of decoFiles) {
try {
const orig = join(origLevelDir, f)
const dest = join(workDir, f)
const meta = await sharp(orig).metadata()
await sharp(orig)
.resize(Math.round(meta.width * ratio), Math.round(meta.height * ratio))
.toFile(dest)
console.log(f)
} catch (e) {
console.error(e)
}
}
await writeFile(join(workDir, basename(path)), JSON.stringify(level))