UNPKG

fy-convertor

Version:

Convert excel/xml/json/bin/protocl/ts/as ...

666 lines (648 loc) 28.8 kB
import fs from "fs-extra"; import _ from "lodash"; import path from "path"; import { indent } from "../tools/vendor.js"; import { isComplexType } from "./def.js"; import { ProtocolStructParser } from "./ProtocolStructParser.js"; import { SvnHolder } from "./SvnHolder.js"; import { Xml2CSBytes } from "./Xml2CSBytes.js"; import { toolchain } from "../tools/toolchain.js"; export class Xml2Protocol { static ins; static get Instance() { if (!Xml2Protocol.ins) Xml2Protocol.ins = new Xml2Protocol(); return Xml2Protocol.ins; } protocolXmlPath; protocolPath; protocolPathsToSync = []; needSafeprintf = false; needLocalize = false; logger = 'uts.logError'; async execute() { const jsEncodeDecode = toolchain.projCfg.xml2protocol?.jsEncodeDecode === 'YES'; const useCSBytes = toolchain.projCfg.xml2protocol?.useCSBytes === 'YES' || toolchain.projCfg.xml2protocol?.useCSBytes === 'YES_V2'; console.log('use jsEncodeDecode?', jsEncodeDecode); console.log('use useCSBytes?', useCSBytes); if (toolchain.projCfg.Project.ProjectType === 'H5ts') this.logger = 'console.error'; const temp = path.join(toolchain.options.workspace, toolchain.options.project); this.protocolXmlPath = path.join(temp, 'protocolXml'); this.protocolPath = path.join(temp, 'ts/protocol'); const ssPath = path.join(temp, 'ss'); const ssPathsToSync = []; const bytesPath = toolchain.projCfg.xml2protocol?.bytesFile || 'project/Assets/AssetSources/net/ss.bytes'; // 更新svn await SvnHolder.Instance.checkSVN(!toolchain.options.debug, this.protocolXmlPath, toolchain.projCfg.Svn.SvrSvn + 'protocol'); await this.initClientSVNs(jsEncodeDecode, toolchain.projCfg.Svn.ClientSvn, this.protocolPath, ssPath, bytesPath); if (toolchain.projCfg.Sync) { for (let i = 0, len = toolchain.projCfg.Sync.length; i < len; i++) { const pp = path.join(temp, `ts/protocolToSync${i}`); const sp = path.join(temp, `ssToSync${i}`); this.protocolPathsToSync.push(pp); ssPathsToSync.push(sp); await this.initClientSVNs(jsEncodeDecode, toolchain.projCfg.Sync[i], pp, sp, bytesPath); } } if (toolchain.projCfg.Project.ProjectType !== 'H5ts') { // unity项目还需chekcout cfg.json检查是否开启翻译 const cfgPath = path.join(temp, 'cfg'); await SvnHolder.Instance.checkSVN(!toolchain.options.debug, cfgPath, toolchain.projCfg.Svn.ClientSvn + 'project/platform/cfg.json'); const cfg = await fs.readJson(path.join(cfgPath, 'cfg.json')); if (cfg.global?.localize) { this.needLocalize = true; } } const allStructs = await ProtocolStructParser.Instance.readStructs(this.protocolXmlPath, toolchain.projCfg); // 读入黑名单,暂时不启用本功能,因为跳过某些字段,如果后台不配合删除,前台需要自己对buff进行偏移,很麻烦 // const blacklistTxt = path.join(this.protocolPath, '.blacklist.txt'); // await ProtocolStructParser.Instance.readBlacklist(blacklistTxt, (s) => s.endsWith('Request') || s.endsWith('Response') || s.endsWith('Notify')); const bodyDef = ProtocolStructParser.Instance.getStructDef('CSMsgBody'); // structname -> msgid, etc: OpenBox_Notify -> MsgID_OpenBox_Notify const msgidMap = {}; const rawRequests = []; const requestMap = {}; const rspntfMap = {}; const allVerRspntfMap = {}; const notUsedCollections = []; for (const entry of bodyDef.entries) { if (!entry._attributes.value) continue; const et = entry._attributes.type; if (!et.endsWith('Request') && !et.endsWith('Response') && !et.endsWith('Notify')) { console.error(`[ERROR]Invalid type ${et}, should be Request/Response/Notify`); process.exit(1); } let msgIds = msgidMap[et]; if (!msgIds) msgidMap[et] = msgIds = []; msgIds.push(entry._attributes.value); const etDef = ProtocolStructParser.Instance.getStructDef(et); let clientUsed = false, supportEncode = false, decodeAllVersion = false; if (etDef._attributes.convertOption) { const cp = etDef._attributes.convertOption.split(','); if (cp.includes('clientUsed')) { clientUsed = true; } supportEncode = cp.includes('supportEncode'); if (cp.includes('decodeAllVersion')) { decodeAllVersion = true; } } if (toolchain.projCfg.xml2protocol?.whitelist && !clientUsed) { notUsedCollections.push(et); continue; } if (et.endsWith('Request')) { rawRequests.push(et); this.collectComplexStructs(et, requestMap); } if (supportEncode) { this.collectComplexStructs(et, requestMap); } if (et.endsWith('Response') || et.endsWith('Notify')) { this.collectComplexStructs(et, rspntfMap); if (decodeAllVersion) { this.collectComplexStructs(et, allVerRspntfMap); } } } rawRequests.sort(); const orphans = []; // 处理孤儿结构 for (const str of allStructs) { if (!requestMap[str] && !rspntfMap[str]) { const def = ProtocolStructParser.Instance.getStructDef(str); if (!def) { console.error('No def for structure:', str); continue; } if (def._attributes.convertOption) { const cp = def._attributes.convertOption.split(','); if (cp.includes('clientUsed')) { orphans.push(str); } } } } const requests = Object.keys(requestMap); const requestIds = []; // 检查Response msgid for (const rqs of rawRequests) { requestIds.push(...msgidMap[rqs]); } const rspntf = Object.keys(rspntfMap); const allVerRspntf = Object.keys(allVerRspntfMap); requests.sort(); rspntf.sort(); allVerRspntf.sort(); // Protocol.d.ts const structs = _.union(requests, rspntf, orphans); structs.sort(); await this.convert(structs, jsEncodeDecode); // SendMsgUtil.ts await this.makeSendMsgUtil(rawRequests, msgidMap); // Macros.ts const macros = ProtocolStructParser.Instance.getAllMacros(); await this.makeMacros(macros, requestIds); await this.makeMacrosDTS(macros, requestIds); if (jsEncodeDecode) { // decoder await this.makeDecodeBase(); if (allVerRspntf.length > 0) { await this.makeLegacyDecoder(allVerRspntf, msgidMap); } await this.makeDecoder(rspntf, msgidMap); // encoder await this.makeEncoder(requests, msgidMap); } // ss.bin const bytesFile = path.basename(bytesPath); if (useCSBytes) { Xml2CSBytes.write(path.join(ssPath, bytesFile)); } else if (!jsEncodeDecode) { await fs.copyFile(path.join(this.protocolXmlPath, 'SS.bin'), path.join(ssPath, bytesFile)); } // 提交svn if (!toolchain.options.debug) { console.log("Committing..."); if (jsEncodeDecode) { await SvnHolder.Instance.commitSVN('xml2protocol@fy-convertor~', this.protocolPath); } if (!jsEncodeDecode || useCSBytes) { await SvnHolder.Instance.commitSVN('xml2protocol@fy-convertor~', this.protocolPath, ssPath); } // 同步 if (toolchain.projCfg.Sync) { for (let i = 0, len = toolchain.projCfg.Sync.length; i < len; i++) { console.log(`Syncing to ${toolchain.projCfg.Sync[i]}...`); const pp = this.protocolPathsToSync[i]; await fs.copy(this.protocolPath, pp, { filter: s => s.endsWith('.ts') }); if (jsEncodeDecode) { await SvnHolder.Instance.commitSVN('xml2protocol@fy-convertor~', pp); } if (!jsEncodeDecode || useCSBytes) { const sp = ssPathsToSync[i]; await fs.copy(ssPath, sp, { filter: s => s.endsWith('.bin') }); await SvnHolder.Instance.commitSVN('xml2protocol@fy-convertor~', pp, sp); } } } } else { console.log("Debug mode, committing skipped."); } // 输出not used if (notUsedCollections.length > 0) { console.log(`${notUsedCollections.length} structures omitted, add "convertOption='clientUsed'":`); console.log(`已忽略${notUsedCollections.length}个结构,如果需要转出,请添加"convertOption='clientUsed'":`); console.log(notUsedCollections.join(', ')); } } async initClientSVNs(jsEncodeDecode, repository, protocolPath, ssPath, bytesPath) { if (toolchain.projCfg.Project.ProjectType === 'H5ts') { await SvnHolder.Instance.checkSVN(true, protocolPath, repository + (toolchain.projCfg.xml2protocol?.protocolRoot ?? 'project/src/automatic/protocol')); } else { await SvnHolder.Instance.checkSVN(true, protocolPath, repository + (toolchain.projCfg.xml2protocol?.protocolRoot ?? 'project/TsScripts/System/protocol')); } if (!jsEncodeDecode) { await SvnHolder.Instance.checkSVN(true, ssPath, toolchain.projCfg.Svn.ClientSvn + path.dirname(bytesPath)); } } collectComplexStructs(structName, map) { if (map[structName]) return; map[structName] = true; const def = ProtocolStructParser.Instance.getStructDef(structName); for (const e of def.entries) { if (e._attributes.safeprintf) this.needSafeprintf = true; if (isComplexType(e._attributes.type)) { this.collectComplexStructs(e._attributes.type, map); } } } async convert(structs, jsEncodeDecode) { let tool = 'js'; if (toolchain.projCfg.xml2protocol.useCSBytes === 'YES_V2') { tool = 'ss.bytes,版本2(支持safeprintf)'; } else if (toolchain.projCfg.xml2protocol.useCSBytes === 'YES') { tool = 'ss.bytes,版本1(不支持safeprintf)'; } let content = `/** * 协议结构定义,由fy-convertor根据协议xml生成 * @encode_decode ${tool} */ declare module Protocol { export type FyMsg<T = any> = { m_stMsgHead: MsgHead; m_msgBody: T; } export type MsgHead = { m_shMsgVersion: number; m_uiTimeStamp_Low: number; m_uiTimeStamp_High: number; m_uiMsgID: number; m_uiUin: number; m_iFeedback: number; m_uiBodyLength: number; } `; for (let s of structs) { const code = ProtocolStructParser.Instance.makeStructCode(s, 'type'); if (code) { content += indent(code); } } content += '}\n'; await fs.writeFile(path.join(this.protocolPath, 'Protocol.d.ts'), content, 'utf-8'); } async makeSendMsgUtil(requests, msgidMap) { let body = ''; for (let s of requests) { const structDef = ProtocolStructParser.Instance.makeSendMsgCode(s, msgidMap[s]); if (structDef) body += indent(structDef); } const ver = ProtocolStructParser.Instance.getMacro('VERSION')._attributes.value; const content = `import { Macros } from './Macros.js'; /**Request协议组包,由fy-convertor根据协议xml生成*/ export class SendMsgUtil { private static readonly _msg: Protocol.FyMsg = {m_stMsgHead:{m_shMsgVersion:${ver}, m_uiTimeStamp_Low:0, m_uiTimeStamp_High:0, m_uiMsgID:0, m_uiUin:0, m_iFeedback:0, m_uiBodyLength:0}} as Protocol.FyMsg; private static readonly _bodyObjects: Record<number, any> = {}; static getCacheObj(msgid: number): object { return SendMsgUtil._bodyObjects[msgid]; } ${body} }`; await fs.writeFile(path.join(this.protocolPath, 'SendMsgUtil.ts'), content, 'utf-8'); } async makeDecodeBase() { const importByte = this.getByteImportStatement('../../'); let content; if (this.needSafeprintf) { if (this.needLocalize) { content = `${importByte} import { ArrayUtil } from "System/utils/ArrayUtil.js"; export declare type DecodeFuncMap = { [msgId: number]: (body: any, byte: Byte) => typeof body }; export class DecodeBase { // 所有非UGC的string字段都要定义safeprintf字段,以便处理协议时自动进行翻译 protected __safeprintf(raw: string): string { if (!raw || raw.search(/[\\u4e00-\\u9fa5]+/) < 0) return raw; const params: string[] = []; let str = raw.replace(/{(.+?)}/g, (substring: string, ...args: any[]) => { const cnt = params.length; params.push(args[0]); return \`{\${cnt}}\`; }); // 注意{}是保留符号,若玩家UGC内容中包含{},可能导致CS代码报错 str = I18N.I18NMgr.TranslatePrintf(str, ArrayUtil.toStringArray(params)); return str; } } `; } else { content = `${importByte} import { ArrayUtil } from "System/utils/ArrayUtil.js"; export declare type DecodeFuncMap = { [msgId: number]: (body: any, byte: Byte) => typeof body }; export class DecodeBase { // 所有非UGC的string字段都要定义safeprintf字段,以便处理协议时自动进行翻译 protected __safeprintf(raw: string): string { if (!raw || raw.search(/[\\u4e00-\\u9fa5]+/) < 0) return raw; const params: string[] = []; let str = raw.replace(/{(.+?)}/g, (substring: string, ...args: any[]) => { const cnt = params.length; params.push(args[0]); return \`{\${cnt}}\`; }); for (let i = 0, len = params.length; i < len; i++) { const p = params[i]; if (p[0] == '^') { params[i] = p.substring(1); } } str = uts.format(str, ...params); return str; } } `; } } else { content = `${importByte} export declare type DecodeFuncMap = { [msgId: number]: (body: any, byte: Byte) => typeof body }; export class DecodeBase { } `; } await fs.writeFile(path.join(this.protocolPath, 'DecodeBase.ts'), content, 'utf-8'); } async makeLegacyDecoder(rspntf, msgidMap) { const ver = ProtocolStructParser.Instance.getMacro('VERSION')._attributes.value; let listernContent = ''; let decodeContent = ''; for (const rn of rspntf) { if (ProtocolStructParser.Instance.structIgnored(rn)) continue; const msgIds = msgidMap[rn]; if (msgIds) { const m = msgIds.map((v) => `this.map[${ProtocolStructParser.Instance.getMacro(v)._attributes.value}]`).join(' = '); listernContent += ` ${m} = this._decode${rn}.bind(this);\n`; } decodeContent += indent(ProtocolStructParser.Instance.makeStructDecodeCode(rn), ' '); } const importByte = this.getByteImportStatement('../../../'); let content = `${importByte} import { DecodeBase, DecodeFuncMap } from '../DecodeBase.js'; import { DrUtil } from '../../../buf/DrUtil.js'; import { Macros } from '../Macros.js'; /**协议解码,由fy-convertor根据协议xml生成*/ export class DecodeUtil${ver} extends DecodeBase { public map: DecodeFuncMap = {}; constructor() { super(); // 使用bind(this)而非delegate,以便进行try catch ${listernContent} } ${decodeContent} } `; const p = path.join(this.protocolPath, 'legacy'); let oldVer = Number(ver) - 1; while (oldVer > 0) { const oldFile = path.join(p, `DecodeUtil${oldVer}.ts`); if (fs.existsSync(oldFile)) { const oldContent = await fs.readFile(oldFile, 'utf-8'); if (oldContent === content) { // 和上一次的版本相同,则不重复生成 return; } // 只和最近的版本进行比较 break; } oldVer--; } await fs.ensureDir(p); await fs.writeFile(path.join(p, `DecodeUtil${ver}.ts`), content, 'utf-8'); } async makeDecoder(rspntf, msgidMap) { const importByte = this.getByteImportStatement('../../'); const ver = ProtocolStructParser.Instance.getMacro('VERSION')._attributes.value; let listernContent = ''; let decodeContent = ''; let legacyImports = ''; for (const rn of rspntf) { if (ProtocolStructParser.Instance.structIgnored(rn)) continue; const msgIds = msgidMap[rn]; if (msgIds) { const m = msgIds.map((v) => `this.map[${ProtocolStructParser.Instance.getMacro(v)._attributes.value}]`).join(' = '); listernContent += ` ${m} = this._decode${rn}.bind(this);\n`; } decodeContent += indent(ProtocolStructParser.Instance.makeStructDecodeCode(rn), ' '); } // 加入legacy版本 const legacyRoot = path.join(this.protocolPath, 'legacy'); if (fs.existsSync(legacyRoot)) { const legacyVers = []; const files = await fs.readdir(legacyRoot); for (const f of files) { const mch = f.match(/DecodeUtil(\d+)/); if (mch != null) legacyVers.push(Number(mch[1])); } legacyVers.sort(); let floor = 1; for (let lvi = 0, lvlen = legacyVers.length; lvi < lvlen; lvi++) { const legacyVer = legacyVers[lvi]; legacyImports += `\nimport { DecodeUtil${legacyVer} } from './legacy/DecodeUtil${legacyVer}.js';`; if (legacyVer === floor) { listernContent += ` this.legacyMap[${legacyVer}] = new DecodeUtil${legacyVer}().map;`; } else { listernContent += ` const map${legacyVer} = new DecodeUtil${legacyVer}().map; for (let i = ${floor}; i <= ${legacyVer}; i++) { this.legacyMap[i] = map${legacyVer}; }`; } floor = legacyVer + 1; } } let content = `${importByte} import { DecodeBase, DecodeFuncMap } from './DecodeBase.js';${legacyImports} import { DrUtil } from '../../buf/DrUtil.js'; import { Macros } from './Macros.js'; /**协议解码,由fy-convertor根据协议xml生成*/ export class DecodeUtil extends DecodeBase { private map: DecodeFuncMap = {}; private legacyMap: { [ver: number]: DecodeFuncMap } = {}; constructor() { super(); // 使用bind(this)而非delegate,以便进行try catch ${listernContent} } public decodeMsgHead(msg: Protocol.FyMsg, byte: Byte): Protocol.FyMsg { if (!msg) msg = {} as Protocol.FyMsg; let body = msg.m_stMsgHead; if (!body) msg.m_stMsgHead = body = {} as Protocol.MsgHead; body.m_shMsgVersion = byte.getInt16(); body.m_uiTimeStamp_Low = byte.getUint32(); body.m_uiTimeStamp_High = byte.getUint32(); body.m_uiMsgID = byte.getUint32(); body.m_uiUin = byte.getUint32(); body.m_iFeedback = byte.getInt32(); body.m_uiBodyLength = byte.getUint32(); return msg; } public decodeBody(msg: Protocol.FyMsg, byte: Byte): boolean { const func = this.map[msg.m_stMsgHead.m_uiMsgID]; if (func) { try { msg.m_msgBody = func(msg.m_msgBody, byte); } catch(e) { ${this.logger}(\`协议\${msg.m_stMsgHead.m_uiMsgID}解包失败,前台版本号:${ver},后台版本号:\${msg.m_stMsgHead.m_shMsgVersion}\`); if (e instanceof Error) ${this.logger}(e.stack); return false; } return true; } else { byte.pos = byte.pos + msg.m_stMsgHead.m_uiBodyLength; } return false; } public decodeBodyWithVersion(msgId: number, body: any, ver: number, byte: Byte): boolean { let map: DecodeFuncMap; if (ver === Macros.VERSION) { map = this.map; } else { map = this.legacyMap[ver]; if (map == null) { ${this.logger}(\`没有对应版本的解包库:\${ver}\`); return false; } } const func = map[msgId]; if (func) { try { func(body, byte); } catch(e) { ${this.logger}(\`协议\${msgId}解包失败,版本号:\${ver}\`); if (e instanceof Error) ${this.logger}(e.stack); return false; } return true; } return false; } ${decodeContent} } `; await fs.writeFile(path.join(this.protocolPath, 'DecodeUtil.ts'), content, 'utf-8'); } async makeEncoder(rspntf, msgidMap) { const importByte = this.getByteImportStatement('../../'); const ver = ProtocolStructParser.Instance.getMacro('VERSION')._attributes.value; let listernContent = ''; let encodeContent = ''; for (const rn of rspntf) { if (ProtocolStructParser.Instance.structIgnored(rn)) continue; const msgIds = msgidMap[rn]; if (msgIds) { const m = msgIds.map((v) => `this.map[${ProtocolStructParser.Instance.getMacro(v)._attributes.value}]`).join(' = '); if (toolchain.projCfg.Project.ProjectType === 'H5ts') { listernContent += ` ${m} = Laya.Handler.create(this, this._encode${rn}, null, false);\n`; } else { listernContent += ` ${m} = delegate(this, this._encode${rn});\n`; } } encodeContent += indent(ProtocolStructParser.Instance.makeStructEncodeCode(rn), ' '); } let func; let call; if (toolchain.projCfg.Project.ProjectType === 'H5ts') { func = 'Laya.Handler'; call = 'func.runWith([body, byte])'; } else { func = '(body: any, byte: Byte) => void'; call = 'func(body, byte)'; } let content = `${importByte} import { DrUtil } from '../../buf/DrUtil.js'; import { Macros } from './Macros.js'; /**协议解码,由fy-convertor根据协议xml生成*/ export class EncodeUtil { private map: { [msgId: number]: ${func} } = {}; constructor() { ${listernContent}; } public encodeMsg(msg: Protocol.FyMsg, byte: Byte): void { const beginPos = byte.pos;//记录当前的起始位置 this._encodeMsgHead(msg.m_stMsgHead, byte);//对头部进行编码 this.encodeBody(msg.m_stMsgHead.m_uiMsgID, msg.m_msgBody, byte); DrUtil.directWriteUint(byte, beginPos + 22, byte.pos - beginPos - 26);//写入body的容量 } private _encodeMsgHead(body: Protocol.MsgHead, byte: Byte): void { byte.writeInt16(body.m_shMsgVersion); // ${ver} byte.writeUint32(body.m_uiTimeStamp_Low); byte.writeUint32(body.m_uiTimeStamp_High); byte.writeUint32(body.m_uiMsgID); byte.writeUint32(body.m_uiUin); byte.writeInt32(body.m_iFeedback); byte.writeUint32(body.m_uiBodyLength); } public encodeBody(msgId: number, body: any, byte: Byte): void { const func = this.map[msgId]; ${call}; } ${encodeContent} } `; await fs.writeFile(path.join(this.protocolPath, 'EncodeUtil.ts'), content, 'utf-8'); } async makeMacros(macros, requestIds) { let macrosContent = ''; let noResponseContent = ''; for (let m of macros) { let comment = m._attributes.value; if (m._attributes.desc) { comment += ', ' + m._attributes.desc; } const e = ProtocolStructParser.Instance.getMacroRelatedEntry(m._attributes.name); if (e != null) { comment += ', ' + e.map((v) => `{@link Protocol.${v.struct}.${v.entry._attributes.name}}`).join(', '); } macrosContent += ` /**${comment}*/\n`; macrosContent += ` ${m._attributes.name} = ${m._attributes.value},\n`; if (requestIds.includes(m._attributes.name)) { const rsp = m._attributes.name.replace(/Request$/, 'Response'); const rspDef = ProtocolStructParser.Instance.getMacro(rsp); if (rspDef != null) { if (Number(m._attributes.value) + 1 !== Number(rspDef._attributes.value)) { noResponseContent += ` /**{@link ${m._attributes.name}} vs {@link ${rspDef._attributes.name}}*/ ${m._attributes.value}: ${rspDef._attributes.value}, `; } } else { noResponseContent += ` /**{@link ${m._attributes.name}}*/ ${m._attributes.value}: 0, `; } } } let content = `/* eslint-disable @typescript-eslint/no-duplicate-enum-values */ /**协议使用的宏定义,由fy-convertor根据协议xml生成*/ export const enum Macros { ${macrosContent} } export class MsgIdMapper { private static readonly ResponseMap = { ${noResponseContent} }; public static getResponseId(requestId: number): number { const mapId = MsgIdMapper.ResponseMap[requestId]; return mapId == null ? requestId + 1 : 0; } } `; await fs.writeFile(path.join(this.protocolPath, 'Macros.ts'), content, 'utf-8'); } async makeMacrosDTS(macros, requestIds) { if (toolchain.projCfg.xml2protocol?.accurateUnion != 'YES') return; let macrosContent = ''; for (let m of macros) { let comment = m._attributes.value; if (m._attributes.desc) { comment += ', ' + m._attributes.desc; } const e = ProtocolStructParser.Instance.getMacroRelatedEntry(m._attributes.name); if (e != null) { comment += ', ' + e.map((v) => `{@link Protocol.${v.struct}.${v.entry._attributes.name}}`).join(', '); } macrosContent += ` /**${comment}*/\n`; macrosContent += ` export type ${m._attributes.name} = ${m._attributes.value};\n`; } let content = `/* eslint-disable @typescript-eslint/no-duplicate-enum-values */ /**协议使用的宏定义,由fy-convertor根据协议xml生成*/ declare module Macros { ${macrosContent} } `; await fs.writeFile(path.join(this.protocolPath, 'Macros.d.ts'), content, 'utf-8'); } getByteImportStatement(rel) { return toolchain.projCfg.Project.ProjectType === 'H5ts' ? 'import Byte = Laya.Byte;' : `import { Byte } from "${rel}buf/Byte.js";`; } } //# sourceMappingURL=Xml2Protocol.js.map