fy-convertor
Version:
Convert excel/xml/json/bin/protocl/ts/as ...
666 lines (648 loc) • 28.8 kB
JavaScript
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) => `{ 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) => `{ 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