Files
aklive2d/packages/music/index.ts
2025-08-02 19:48:09 +08:00

136 lines
4.4 KiB
TypeScript

import path from 'node:path'
import { file } from '@aklive2d/libs'
import { githubDownload } from '@aklive2d/downloader'
import config from '@aklive2d/config'
import type {
DisplayMetaTable,
AudioDataTable,
MusicTable,
MusicFileMapping,
MusicFiles,
MusicItem,
MusicDataItem,
MusicMapping,
} from './types.ts'
const AUTO_UPDATE_FOLDER = path.resolve(
import.meta.dirname,
config.dir_name.auto_update
)
export const DATA_DIR = path.resolve(import.meta.dirname, config.dir_name.data)
const MUSIC_TABLE_JSON = path.join(
AUTO_UPDATE_FOLDER,
config.module.music.music_table_json
)
const download = async () => {
const display_meta_table_json = path.resolve(
AUTO_UPDATE_FOLDER,
config.module.music.display_meta_table_json
)
const audio_data_json = path.resolve(
AUTO_UPDATE_FOLDER,
config.module.music.audio_data_json
)
const metaTable: DisplayMetaTable = await githubDownload(
`https://api.github.com/repos/Kengxxiao/ArknightsGameData/commits?path=zh_CN/gamedata/excel/display_meta_table.json`,
`https://raw.githubusercontent.com/Kengxxiao/ArknightsGameData/master/zh_CN/gamedata/excel/display_meta_table.json`,
display_meta_table_json
)
const audioDataTable: AudioDataTable = await githubDownload(
`https://api.github.com/repos/Kengxxiao/ArknightsGameData/commits?path=zh_CN/gamedata/excel/audio_data.json`,
`https://raw.githubusercontent.com/Kengxxiao/ArknightsGameData/master/zh_CN/gamedata/excel/audio_data.json`,
audio_data_json
)
return {
metaTable,
audioDataTable,
}
}
const generateMapping = () => {
const musicFolder = DATA_DIR
const musicTableContent = file.readSync(MUSIC_TABLE_JSON)
const musicTable: MusicTable = musicTableContent
? JSON.parse(musicTableContent)
: null
const musicFileMapping: MusicFileMapping = {}
const musicFiles: MusicFiles = []
if (!musicTable) throw new Error('Music table not found')
for (const item of musicTable) {
const key = `${item.id}.png`
musicFileMapping[key] = {} as MusicItem
if (item.intro) {
const filename = `${item.intro.split('/').pop()}.ogg`
musicFileMapping[key].intro = filename
musicFiles.push({
filename,
source: musicFolder,
})
} else {
musicFileMapping[key].intro = null
}
if (item.loop) {
const filename = `${item.loop.split('/').pop()}.ogg`
musicFileMapping[key].loop = filename
musicFiles.push({
filename,
source: musicFolder,
})
} else {
musicFileMapping[key].loop = null
}
}
return {
musicFiles,
musicFileMapping,
}
}
export const mapping: MusicMapping = generateMapping()
export const update = async () => {
const { metaTable, audioDataTable } = await download()
const musicTable = audioDataTable.musics
const musicBank = audioDataTable.bgmBanks
const musicBankAlias = audioDataTable.bankAlias
const musicData: MusicDataItem[] =
metaTable.homeBackgroundData.homeBgDataList.reduce((acc, cur) => {
if (cur.multiFormList.length > 1)
console.warn(`${cur.bgId} has multiple musicIds`)
acc.push({
id: cur.bgId,
musicId: cur.multiFormList[0].bgMusicId,
})
return acc
}, [] as MusicDataItem[])
const list = []
for (const item of musicData) {
const bankItem = musicTable.find((el) => item.musicId === el.id)
if (typeof bankItem === 'undefined')
console.warn(`No music found for id ${item.musicId}`)
let bankName = bankItem!.bank
if (typeof musicBankAlias[bankName] !== 'undefined') {
bankName = musicBankAlias[bankName]
}
const obj = musicBank.find((el) => bankName === el.name)
if (typeof obj === 'undefined')
console.warn(`No bank found for name ${bankName}`)
list.push({
id: item.id,
intro: obj!.intro,
loop: obj!.loop,
})
}
list.push({
id: 'operator_bg',
intro: 'm_sys_void_intro',
loop: 'm_sys_void_loop',
})
file.writeSync(JSON.stringify(list, null), MUSIC_TABLE_JSON)
}