import { readFileSync } from 'node:fs'; import { DOMParser } from '@xmldom/xmldom'; /** * 读取 Game_Surface_3 风格的 Layer XML (UTF-8 编码), 解析 Layer + Spirit 字段. * * 协议来源: docs/protocol/ (服务器零改动). XML 结构与 save/Layer*.xml 一致: * * * * * ... * * * * * 数据源权威: 字段缺失/不存在一律返回 undefined (不上游兜底, 由下游显式判错). * * @param {string} path - 文件路径 (相对 cwd 或绝对) * @returns {{ layerId: string|undefined, layerName: string|undefined, spirits: Array<{ id, name, type, imgResID, x, y, w, h, group, indexOfLayer }> }} */ export function readLayerXml(path) { const text = readFileSync(path, 'utf8'); const doc = new DOMParser().parseFromString(text, 'text/xml'); const getProp = (el, name) => { const prop = Array.from(el.getElementsByTagName('Property')) .find(p => p.getAttribute('Name') === name); return prop?.getAttribute('Value'); }; const layerEl = doc.getElementsByTagName('Layer')[0]; const layerPropList = layerEl.getElementsByTagName('PropertyList')[0]; const layerId = getProp(layerPropList, 'ID'); const layerName = getProp(layerPropList, 'Name'); const spiritEls = doc.getElementsByTagName('Spirit'); const spirits = Array.from(spiritEls).map(sp => { const propList = sp.getElementsByTagName('PropertyList')[0]; return { id: getProp(propList, 'ID'), name: getProp(propList, 'Name'), type: getProp(propList, 'SpiritType'), imgResID: getProp(propList, 'ImgResID'), x: getProp(propList, 'X'), y: getProp(propList, 'Y'), w: getProp(propList, 'Width'), h: getProp(propList, 'Height'), group: getProp(propList, 'BelongGroupID'), indexOfLayer: getProp(propList, 'IndexOfLayer'), }; }); return { layerId, layerName, spirits }; }