genPomeloProto.js 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191
  1. ///**
  2. // * Created by lusongjie on 2015/4/17.
  3. // */
  4. //处理参数
  5. function processArgv() {
  6. var ret = {};
  7. var args = process.argv.slice(2);
  8. for (var i in args) {
  9. var list = args[i].split('=');
  10. ret[list[0]] = list[1];
  11. }
  12. return ret;
  13. }
  14. var argv = processArgv();
  15. /*-----------------------------------------------编译proto文件--------------------------------------------------*/
  16. var fs = require('fs');
  17. var ProtoBuf = require("protobufjs");
  18. var util = require("util");
  19. var buildProto = function (argv) {
  20. var builder = ProtoBuf.newBuilder();
  21. var protoDir = argv.input;
  22. fs.readdirSync(protoDir).forEach(function (filename) {
  23. if (!/\.proto$/.test(filename)) {
  24. return;
  25. }
  26. ProtoBuf.loadProtoFile(protoDir + '\\' + filename, builder);
  27. });
  28. builder.build();
  29. return builder;
  30. }
  31. var builder = buildProto(argv);
  32. //console.log(util.inspect(builder,{depth:5}));
  33. /*-----------------------------------------------通用函数--------------------------------------------------*/
  34. //首字母大写
  35. function firstUpperCase(str) {
  36. return str.replace(/\b\w/g, function (m) {
  37. return m.toUpperCase();
  38. });
  39. }
  40. function firstLowerCase(str) {
  41. return str.replace(/\b\w/g, function (m) {
  42. return m.toLowerCase();
  43. });
  44. }
  45. //生成空行
  46. function genSpaceLine() {
  47. return '\n';
  48. }
  49. //生成缩进
  50. function genIndent(nest) {
  51. var str = '';
  52. for (var i = 0; i < nest; ++i) {
  53. str += '\t'
  54. }
  55. return str;
  56. }
  57. //写入文件
  58. function writeFile(output, fileName, code) {
  59. fs.writeFileSync(output + '/' + fileName, code);
  60. }
  61. /*-----------------------------------------------结构解析--------------------------------------------------*/
  62. var handlers = {};
  63. var sockets = {};
  64. function push2handler(str) {
  65. return str.replace(/Push/g, function (m) {
  66. return 'Handler';
  67. });
  68. }
  69. function isPush(name) {
  70. var ret = name.match(/Push$/g);
  71. return ret !== null;
  72. }
  73. function isNotify(name) {
  74. var ret = name.match(/Notify$/g);
  75. return ret !== null;
  76. }
  77. function isRequest(name) {
  78. var ret = name.match(/Request$/g);
  79. return ret !== null;
  80. }
  81. function isHandler(name) {
  82. var ret = name.match(/Handler/g);
  83. return ret !== null;
  84. }
  85. //handler成员变量名
  86. function handlerFieldName(name) {
  87. return name.replace(/\b\w/g, function (m) {
  88. return m.toLowerCase();
  89. });
  90. }
  91. //request函数参数列表
  92. function requestParams(reflectT) {
  93. var array = [];
  94. for (var key in reflectT.children) {
  95. var field = reflectT.children[key];
  96. var type = field.type.name;
  97. if (field.resolvedType != null) {
  98. type = field.resolvedType.name;
  99. }
  100. var params = {
  101. type: type,
  102. name: field.name,
  103. repeated: field.repeated,
  104. required: field.required
  105. };
  106. array.push(params);
  107. }
  108. return array;
  109. }
  110. var socketMap = {
  111. gateHandler: 'GateSocket'
  112. }
  113. var getSocketName = function (name) {
  114. var socket = socketMap[name];
  115. if (socket) {
  116. return socket;
  117. }
  118. return 'GameSocket';
  119. }
  120. /**
  121. * 添加socket
  122. * @param socketName
  123. */
  124. var addSocket = function (socketName) {
  125. if (sockets[socketName] === undefined) {
  126. sockets[socketName] = {
  127. name: socketName,
  128. base: 'PomeloClient',
  129. type: 'socket',
  130. fields: [{
  131. type: 'ProtobufSerializer',
  132. name: 'serializer',
  133. notUppder: true
  134. }],
  135. events: [],
  136. usings: {},
  137. socket: socketName
  138. };
  139. }
  140. }
  141. /***
  142. * 添加handler
  143. * @param reflectT
  144. */
  145. var addHandler = function (reflectT) {
  146. var fullHandlerName = reflectT.parent.name + '.' + reflectT.name;
  147. var handlerName = reflectT.name;
  148. var socketName = getSocketName(handlerName);
  149. if (handlers[fullHandlerName] === undefined) {
  150. handlers[fullHandlerName] = {
  151. name: firstUpperCase(handlerName),
  152. type: 'handler',
  153. fields: [{ type: 'PomeloClient', name: 'socket', skipProp: true },
  154. { type: 'ProtobufSerializer', name: 'serializer', skipProp: true }],
  155. requests: [],
  156. notifies: [],
  157. events: [],
  158. responses: [],
  159. socket: socketName,
  160. ns: reflectT.parent.name
  161. }
  162. if (isHandler(handlerName)) {
  163. //socket的handler数组
  164. sockets[socketName].fields.push({
  165. type: firstUpperCase(handlerName),
  166. name: handlerFieldName(handlerName),
  167. notUppder: true
  168. });
  169. sockets[socketName].usings[reflectT.parent.name] = true;
  170. }
  171. for (var keyRpc in reflectT.children) {
  172. var rpc = reflectT.children[keyRpc];
  173. var rpcName = rpc.name;
  174. var route = fullHandlerName + '.' + rpcName;
  175. //创建request response
  176. if (isRequest(rpcName)) {
  177. handlers[fullHandlerName].requests.push({
  178. route: route,
  179. type: rpcName,
  180. requestType: rpc.resolvedRequestType.name,
  181. responseType: rpc.resolvedResponseType.name,
  182. params: requestParams(rpc.resolvedRequestType)
  183. });
  184. }
  185. //创建notify
  186. else if (isNotify(rpcName)) {
  187. handlers[fullHandlerName].notifies.push({
  188. route: route,
  189. type: rpcName,
  190. requestType: rpc.resolvedRequestType.name,
  191. responseType: rpc.resolvedResponseType.name,
  192. params: requestParams(rpc.resolvedRequestType)
  193. });
  194. }
  195. //创建event
  196. else if (isPush(rpcName)) {
  197. var pushHandler = push2handler(handlerName);
  198. var event = {
  199. route: route,
  200. type: rpcName,
  201. requestType: rpc.resolvedRequestType.name,
  202. responseType: rpc.resolvedResponseType.name,
  203. params: requestParams(rpc.resolvedRequestType),
  204. handler: pushHandler
  205. };
  206. try {
  207. var fullPushHandler = reflectT.parent.name + '.' + pushHandler;
  208. handlers[fullPushHandler].events.push(event);
  209. sockets[socketName].events.push(event);
  210. }
  211. catch (e) {
  212. console.log("generate error: handler name must br same as filename!!!!!: " + fullPushHandler + "\n" + e);
  213. throw e;
  214. }
  215. }
  216. else {
  217. throw new Error("api must postfix with Push or Request or Notify: " + fullHandlerName + " " + rpcName);
  218. }
  219. // handlers[service.name].responses.push({name: rpc.response, fields: responseParams(key)});
  220. if (rpc.responseName !== 'Void') {
  221. handlers[fullHandlerName].fields.push({ type: rpc.responseName, name: 'last' + rpc.responseName });
  222. }
  223. }
  224. }
  225. }
  226. /**
  227. * 添加节点
  228. * @param reflectT
  229. */
  230. var addNode = function (reflectT) {
  231. //service对应handler
  232. if (reflectT.className === 'Service') {
  233. addHandler(reflectT);
  234. return;
  235. }
  236. //message对应message
  237. else if (reflectT.className === 'Message') {
  238. // addMessage(reflectT);
  239. }
  240. //遍历子节点
  241. for (var key in reflectT.children) {
  242. addNode(reflectT.children[key]);
  243. }
  244. }
  245. //创建所有的对象
  246. var createAll = function () {
  247. addSocket('GateSocket');
  248. addSocket('GameSocket');
  249. addNode(builder.ns);
  250. }
  251. createAll();
  252. //console.log(util.inspect(handlers, false, null, true));
  253. ///*--------------------------------------------C#代码生成--------------------------------------------------------*/
  254. //成员变量类型名字
  255. function fieldTypeName(field) {
  256. if (field.repeated == 'repeated') {
  257. return 'List<' + field.type + '>';
  258. }
  259. return field.type;
  260. }
  261. //protobuf 和c#的基本类型映射
  262. var typeMap = {
  263. 'Int32': 'int',
  264. 'int32': 'int',
  265. 'uInt32': 'uint',
  266. 'Int64': 'long',
  267. 'int64': 'long',
  268. 'uInt64': 'ulong',
  269. 'string': 'string',
  270. 'bytes': 'byte[]'
  271. }
  272. //转化为c#的类型
  273. function toCSharpType(type) {
  274. var ret = typeMap[type];
  275. if (ret === undefined) {
  276. ret = type;
  277. }
  278. return ret;
  279. }
  280. //生成文件头注释
  281. function genComment() {
  282. var code = '/*-----------------------------------------------\n';
  283. code += ' *本文件由代码生成器自动生成,\n';
  284. code += ' *千万不要修改本文件的任何代码,\n';
  285. code += ' *修改的的任何代码都会被覆盖掉!\n';
  286. code += ' --------------------------------------------------*/\n';
  287. code += genSpaceLine();
  288. return code;
  289. }
  290. //生成引用
  291. function genUsing(usings) {
  292. var pre = 'using System.IO;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing Pomelo.DotNetClient;\n';
  293. if (usings) {
  294. for (var key in usings) {
  295. pre += 'using pomelo.' + key + ';\n';
  296. }
  297. }
  298. return pre;
  299. }
  300. //生成名称空间开头
  301. function genNameSpaceBegin(indent, name) {
  302. return genIndent(indent) + 'namespace ' + name + '\n{';
  303. }
  304. //生成名称空间结尾
  305. function genNameSpaceEnd(indent) {
  306. return genSpaceLine() + genIndent(indent) + '}';
  307. }
  308. //生成类开头
  309. function genClassBegin(indent, name, base) {
  310. var str = genIndent(indent) + 'public class ' + name;
  311. if (base !== undefined) {
  312. str += ' : ' + base;
  313. }
  314. return str + '\n' + genIndent(indent) + '{\n';
  315. }
  316. //生成类结尾
  317. function genClassEnd(indent) {
  318. return genSpaceLine() + genIndent(indent) + '}';
  319. }
  320. //生成成员变量
  321. function genFieldDeclare(indent, field) {
  322. var type = fieldTypeName(field);
  323. var code = genIndent(indent) + 'private ' + type + ' _' + field.name;
  324. code += ';\n';
  325. return code;
  326. }
  327. //生成成员变量属性
  328. function genFieldProperty(indent, field) {
  329. var code = genIndent(indent) + 'public ' + fieldTypeName(field) + ' ' + field.name + '\n';
  330. code += genIndent(indent) + '{\n';
  331. code += genIndent(indent + 1) + 'get { return _' + field.name + ';}\n';
  332. code += genIndent(indent + 1) + 'set { _' + field.name + ' = value; }\n';
  333. code += genIndent(indent) + '}\n';
  334. return code;
  335. }
  336. //生成函数开头
  337. function genMethodBegin(indent, name, params, ret) {
  338. var code = genIndent(indent) + 'public ';
  339. if (ret !== undefined) {
  340. code += ret + ' ';
  341. }
  342. code += name + '(';
  343. if (params !== undefined) {
  344. for (var i in params) {
  345. var param = params[i];
  346. // code+= fieldTypeName(param)+' '+ param.name;
  347. if (param.repeated) {
  348. code += 'List<' + toCSharpType(param.type) + '> ' + param.name;
  349. }
  350. else {
  351. code += toCSharpType(param.type) + ' ' + param.name;
  352. }
  353. if (param.default != undefined) {
  354. code += ' = ' + param.default;
  355. }
  356. code += ',';
  357. }
  358. if (code[code.length - 1] === ',') {
  359. code = code.substring(0, code.length - 1);
  360. }
  361. }
  362. code += ')\n' + genIndent(indent) + '{\n';
  363. return code;
  364. }
  365. //生成函数结尾
  366. function genMethodEnd(indent) {
  367. return genSpaceLine() + genIndent(indent) + '}';
  368. }
  369. //生成构造函数
  370. function genConstuctor(indent, classInfo) {
  371. var code = '';
  372. if (classInfo.type === 'socket') {
  373. code += genMethodBegin(indent, classInfo.name);
  374. for (var i in classInfo.fields) {
  375. var field = classInfo.fields[i];
  376. if (field.type === 'ProtobufSerializer') {
  377. // code += genIndent(indent + 1) + '_' + field.name + ' = new ' + field.type + '();\n';
  378. code += genIndent(indent + 1) + '_' + field.name + ' = base.Serializer;\n';
  379. }
  380. else {
  381. code += genIndent(indent + 1) + '_' + field.name + ' = new ' + field.type + '(this,_serializer);\n';
  382. }
  383. }
  384. code += genMethodEnd(indent);
  385. }
  386. else if (classInfo.type === 'handler') {
  387. //静态构造
  388. code += genIndent(indent) + "static " + classInfo.name + "()\n";
  389. code += genIndent(indent) + "{\n"
  390. for (var i in classInfo.events) {
  391. var event = classInfo.events[i];
  392. code += genIndent(indent + 1) + "Pomelo.DotNetClient.EventTypes.RegistPushType(\"" + event.route + "\", typeof(" + event.requestType + "));\n"
  393. }
  394. for (var i in classInfo.requests) {
  395. var request = classInfo.requests[i];
  396. code += genIndent(indent + 1) + "Pomelo.DotNetClient.EventTypes.RegistRequestType(\"" + request.route + "\", typeof(" + request.requestType + "), typeof(" + request.responseType + "));\n"
  397. }
  398. for (var i in classInfo.notifies) {
  399. var notify = classInfo.notifies[i];
  400. code += genIndent(indent + 1) + "Pomelo.DotNetClient.EventTypes.RegistNotifyType(\"" + notify.route + "\", typeof(" + notify.requestType + "));\n"
  401. }
  402. code += genIndent(indent) + "}\n";
  403. //构造
  404. code += genMethodBegin(indent, classInfo.name, [
  405. { type: 'PomeloClient', name: 'socket' },
  406. { type: 'ProtobufSerializer', name: 'serializer' }
  407. ]);
  408. code += genIndent(indent + 1) + 'this._socket = socket;\n';
  409. code += genIndent(indent + 1) + 'this._serializer = serializer;\n';
  410. code += genMethodEnd(indent);
  411. }
  412. return code;
  413. }
  414. //生成request函数
  415. function genRequest(indent, classInfo, request) {
  416. var code = '';
  417. request.params.push({ type: 'Action<PomeloException,' + request.responseType + '>', name: 'cb' });
  418. request.params.push({ type: 'object', name: 'option', default: 'null' });
  419. code += genMethodBegin(indent, request.type, request.params, 'void');
  420. request.params.pop();
  421. request.params.pop();
  422. //code += genIndent(indent + 1) + '_socket.onRequestStart("' + request.route + '", option);\n';
  423. code += genIndent(indent + 1) + request.requestType + ' request = new ' + request.requestType + '();\n';
  424. for (var i in request.params) {
  425. var param = request.params[i];
  426. if (param.repeated) {
  427. code += genIndent(indent + 1) + 'request.' + param.name + '.AddRange(' + param.name + ');\n';
  428. }
  429. else {
  430. code += genIndent(indent + 1) + 'request.' + param.name + '= ' + param.name + ';\n';
  431. }
  432. }
  433. code += '\n';
  434. //code += genIndent(indent+1)+'MemoryStream input = new MemoryStream();\n';
  435. //code += genIndent(indent+1)+'_serializer.Serialize(input, request);\n\n';
  436. var respName = request.responseType;
  437. code += genIndent(indent + 1) + '_socket.request<' + respName + '>(request, (' + respName + ' rsp, out int s2c_code, out string s2c_msg) => {\n';
  438. code += genIndent(indent + 2) + 's2c_code = rsp.s2c_code;\n';
  439. code += genIndent(indent + 2) + 's2c_msg = rsp.s2c_msg;\n';
  440. code += genIndent(indent + 2) + 'return s2c_code == 200;\n';
  441. code += genIndent(indent + 1) + '}, cb, option);\n';
  442. /**
  443. code += genIndent(indent + 1) + '_socket.request("' + request.route + '", _serializer, request, output => {\n';
  444. code += genIndent(indent + 2) + 'try\n';
  445. code += genIndent(indent + 2) + '{\n';
  446. code += genIndent(indent + 3) + 'var stream = (MemoryStream)output;\n';
  447. code += genIndent(indent + 3) + respName + ' response = _serializer.Deserialize(stream, null, typeof(' + respName + ')) as ' + respName + ';\n';
  448. code += genIndent(indent + 3) + 'last' + respName + ' = response;\n';
  449. code += '\n';
  450. code += genIndent(indent + 3) + 'int code = response.s2c_code;\n';
  451. code += genIndent(indent + 3) + 'if (code == 200)\n';
  452. code += genIndent(indent + 3) + '{\n';
  453. code += genIndent(indent + 4) + '_socket.onRequestEnd("' + request.route + '", null, last' + respName + ', option);\n';
  454. code += genIndent(indent + 4) + 'cb(null, last' + respName + ');\n';
  455. code += genIndent(indent + 3) + '}\n';
  456. code += genIndent(indent + 3) + 'else\n';
  457. code += genIndent(indent + 3) + '{\n';
  458. code += genIndent(indent + 4) + 'string msg = response.s2c_msg;\n';
  459. code += genIndent(indent + 4) + 'PomeloException exp = new PomeloException(code, msg);\n';
  460. code += genIndent(indent + 4) + '_socket.onRequestEnd("' + request.route + '",exp, null, option);\n';
  461. code += genIndent(indent + 4) + ' cb(exp, null);\n';
  462. code += genIndent(indent + 3) + '}\n';
  463. code += genIndent(indent + 2) + '}\n';
  464. code += genIndent(indent + 2) + 'catch (Exception e)\n';
  465. code += genIndent(indent + 2) + '{\n';
  466. code += genIndent(indent + 3) + 'PomeloException exp = new PomeloException(501, e.Message + \"\\n\" + e.StackTrace);\n';
  467. code += genIndent(indent + 3) + '_socket.onRequestEnd("' + request.route + '",exp, null, option);\n';
  468. code += genIndent(indent + 3) + 'cb(exp, null);\n';
  469. code += genIndent(indent + 2) + '}\n';
  470. code += genIndent(indent + 2) + 'cb = null;\n';
  471. code += genIndent(indent + 1) + '});\n';
  472. */
  473. code += genMethodEnd(indent);
  474. return code;
  475. }
  476. //生成notify函数
  477. function genNotify(indent, classInfo, notify) {
  478. var code = '';
  479. code += genMethodBegin(indent, notify.type, notify.params, 'void');
  480. code += genIndent(indent + 1) + notify.requestType + ' notify = new ' + notify.requestType + '();\n';
  481. for (var i in notify.params) {
  482. var param = notify.params[i];
  483. if (param.repeated) {
  484. code += genIndent(indent + 1) + 'notify.' + param.name + '.AddRange(' + param.name + ');\n';
  485. }
  486. else {
  487. code += genIndent(indent + 1) + 'notify.' + param.name + '= ' + param.name + ';\n';
  488. }
  489. }
  490. code += '\n';
  491. //code += genIndent(indent+1)+'MemoryStream input = new MemoryStream();\n';
  492. //code += genIndent(indent+1)+'_serializer.Serialize(input, notify);\n\n';
  493. code += genIndent(indent + 1) + '_socket.notify("' + notify.route + '", _serializer, notify);\n';
  494. code += genMethodEnd(indent);
  495. return code;
  496. }
  497. var eventOnName = function (name) {
  498. var ret = name.match(/^on/g) != null;
  499. if (ret) {
  500. return name;
  501. }
  502. return 'on' + firstUpperCase(name);
  503. }
  504. //生成事件响应函数
  505. function genEvent(indent, classInfo, event) {
  506. var code = '';
  507. var responseType = event.requestType;
  508. var eventName = event.type;
  509. var params = [{ type: 'Action<' + responseType + '>', name: 'cb' }];
  510. code += genMethodBegin(indent, eventOnName(eventName), params, 'void');
  511. if (classInfo.type == 'socket') {
  512. code += genIndent(indent + 1) + '_' + event.handler + '.' + eventOnName(eventName) + '(cb);\n';
  513. }
  514. else {
  515. code += genIndent(indent + 1) + '_socket.on_push("' + event.route + '", stream => {\n';
  516. if (event.route === 'area.playerPush.battleEventPush') {
  517. //code += genIndent(indent + 2) + 'BattleEventPush push = new BattleEventPush();\n';
  518. //code += genIndent(indent + 2) + 'push.s2c_data = (stream as MemoryStream).ToArray();\n';
  519. }
  520. else {
  521. //code += genIndent(indent + 2) + responseType + ' push = _serializer.Deserialize(stream, null, typeof(' + responseType + ')) as ' + event.requestType + ';\n';
  522. code += genIndent(indent + 2) + responseType + ' push = stream as ' + event.requestType + ';\n';//_serializer.Deserialize(stream, null, typeof(' + responseType + ')) as ' + event.requestType + ';\n';
  523. code += genIndent(indent + 2) + 'cb(push);\n';
  524. }
  525. code += genIndent(indent + 1) + '});\n';
  526. }
  527. code += genMethodEnd(indent);
  528. return code;
  529. }
  530. //生成类
  531. function genClass(indent, classInfo) {
  532. var code = '';
  533. code += genClassBegin(indent, classInfo.name, classInfo.base);
  534. for (var i in classInfo.fields) {
  535. var field = classInfo.fields[i];
  536. code += genFieldDeclare(indent + 1, field);
  537. }
  538. code += genSpaceLine();
  539. //生成属性
  540. for (var i in classInfo.fields) {
  541. var field = classInfo.fields[i];
  542. if (field.skipProp) {
  543. continue;
  544. }
  545. code += genFieldProperty(indent + 1, field);
  546. code += genSpaceLine();
  547. }
  548. //生成构造函数
  549. code += genConstuctor(indent + 1, classInfo);
  550. code += genSpaceLine();
  551. //生成request
  552. for (var i in classInfo.requests) {
  553. var request = classInfo.requests[i];
  554. code += genRequest(indent + 1, classInfo, request);
  555. code += genSpaceLine();
  556. }
  557. //生成notify
  558. for (var i in classInfo.notifies) {
  559. var notify = classInfo.notifies[i];
  560. code += genNotify(indent + 1, classInfo, notify);
  561. code += genSpaceLine();
  562. }
  563. //生成event
  564. for (var i in classInfo.events) {
  565. var event = classInfo.events[i];
  566. code += genEvent(indent + 1, classInfo, event);
  567. code += genSpaceLine();
  568. }
  569. code += genClassEnd(indent);
  570. return code;
  571. }
  572. //生成文件开头
  573. function genFileBegin(classInfo) {
  574. var code = '';
  575. code += genComment();
  576. code += genUsing(classInfo.usings);
  577. code += genSpaceLine();
  578. var ns = classInfo.ns;
  579. if (!ns) {
  580. ns = 'Pomelo.DotNetClient';
  581. }
  582. else {
  583. ns = 'pomelo.' + ns;
  584. }
  585. code += genNameSpaceBegin(0, ns);
  586. code += genSpaceLine();
  587. return code;
  588. }
  589. //生成文件结尾
  590. function genFileEnd() {
  591. return genNameSpaceEnd(0);
  592. }
  593. function genFile(classInfos) {
  594. var code = '';
  595. code += genFileBegin(classInfos[0]);
  596. for (var i in classInfos) {
  597. code += genClass(1, classInfos[i]);
  598. code += genSpaceLine();
  599. code += genSpaceLine();
  600. }
  601. code += genFileEnd();
  602. return code;
  603. }
  604. //socket文件
  605. for (var keySocket in sockets) {
  606. writeFile(argv.output, sockets[keySocket].name + '.cs', genFile([sockets[keySocket]]));
  607. }
  608. //handler文件
  609. for (var keyHandler in handlers) {
  610. var fileName = handlers[keyHandler].name;
  611. if (isHandler(fileName)) {
  612. writeFile(argv.output, firstUpperCase(fileName) + '.cs', genFile([handlers[keyHandler]]));
  613. }
  614. }
  615. //
  616. ///*--------------------------------------------Lua代码生成--------------------------------------------------------*/
  617. function genLuaMethodBegin(indent, name, params) {
  618. var code = genIndent(indent) + 'function ';
  619. code += name + '(';
  620. if (params !== undefined) {
  621. for (var i in params) {
  622. var param = params[i];
  623. code += param.name;
  624. code += ',';
  625. }
  626. if (code[code.length - 1] === ',') {
  627. code = code.substring(0, code.length - 1);
  628. }
  629. }
  630. code += ')\n';
  631. return code;
  632. }
  633. function genLuaMethodEnd(indent) {
  634. return genIndent(indent) + 'end\n';
  635. }
  636. function fullLuaName(className) {
  637. return 'Pomelo.' + className;
  638. }
  639. function genLuaRequest(indent, classInfo, request) {
  640. var code = '';
  641. request.params.push({ type: 'Action<PomeloException,' + request.responseType + '>', name: 'cb' });
  642. request.params.push({ type: 'object', name: 'option', default: 'null' });
  643. code += genLuaMethodBegin(indent, fullLuaName(classInfo.name) + '.' + request.type, request.params);
  644. request.params.pop();
  645. request.params.pop();
  646. if (request.params.length == 0) {
  647. code += genIndent(indent + 1) + 'local input = nil\n';
  648. }
  649. else {
  650. code += genIndent(indent + 1) + 'local msg = {}\n';
  651. for (var i in request.params) {
  652. var param = request.params[i];
  653. code += genIndent(indent + 1) + 'msg.' + param.name + ' = ' + param.name + '\n';
  654. }
  655. code += genIndent(indent + 1) + 'local input = ' + firstLowerCase(classInfo.name) + '_pb.' + request.requestType + '()\n';
  656. code += genIndent(indent + 1) + 'protobuf.FromMessage(input,msg)\n';
  657. }
  658. if (request.params.length == 0) {
  659. code += genIndent(indent + 1) + 'Socket.Request("' + request.route + '", input,function(stream)\n';
  660. }
  661. else {
  662. code += genIndent(indent + 1) + 'Socket.Request("' + request.route + '", ZZBase64.encode(input:SerializeToString()),function(stream)\n';
  663. }
  664. code += genIndent(indent + 2) + 'stream = ZZBase64.decode(stream)\n';
  665. code += genIndent(indent + 2) + 'local res = ' + firstLowerCase(classInfo.name) + '_pb.' + request.responseType + '()\n';
  666. code += genIndent(indent + 2) + 'res:ParseFromString(stream)\n';
  667. code += genIndent(indent + 2) + 'if(res.s2c_code == 200) then\n';
  668. code += genIndent(indent + 3) + 'Pomelo.' + classInfo.name + '.last' + request.responseType + ' = res\n';
  669. code += genIndent(indent + 3) + 'Socket.OnRequestEnd("' + request.route + '", true)\n';
  670. code += genIndent(indent + 3) + 'cb(nil,res)\n';
  671. code += genIndent(indent + 2) + 'else\n';
  672. code += genIndent(indent + 3) + 'local ex = {}\n';
  673. code += genIndent(indent + 3) + 'if(res.s2c_code) then\n';
  674. code += genIndent(indent + 4) + 'ex.Code = res.s2c_code\n';
  675. code += genIndent(indent + 4) + 'ex.Message = res.s2c_msg\n';
  676. code += genIndent(indent + 3) + 'else\n';
  677. code += genIndent(indent + 4) + 'ex.Code = 501\n';
  678. code += genIndent(indent + 4) + 'ex.Message = \"[LuaXmdsNetClient] ' + request.route + ' decode error!!\"\n';
  679. code += genIndent(indent + 3) + 'end\n';
  680. code += genIndent(indent + 3) + 'Socket.OnRequestEnd("' + request.route + '", false,ex.Code,ex.Message)\n';
  681. code += genIndent(indent + 3) + 'cb(ex,nil)\n';
  682. code += genIndent(indent + 2) + 'end\n';
  683. //code += genIndent(indent+2) + 'if(ex == nil) then\n';
  684. //code += genIndent(indent+3) + fullLuaName(classInfo.name)+'.last'+ request.responseType +' = res\n';
  685. //code += genIndent(indent+2) + 'end\n';
  686. //code += genIndent(indent+2) + 'cb(ex,res)\n';
  687. code += genIndent(indent + 1) + 'end,option)\n';
  688. code += genLuaMethodEnd(indent);
  689. return code;
  690. }
  691. function genLuaNotify(indent, classInfo, notify) {
  692. var code = '';
  693. code += genLuaMethodBegin(indent, fullLuaName(classInfo.name) + '.' + notify.type, notify.params);
  694. if (notify.params.length == 0) {
  695. code += genIndent(indent + 1) + 'local input = nil\n';
  696. }
  697. else {
  698. code += genIndent(indent + 1) + 'local msg = {}\n';
  699. for (var i in notify.params) {
  700. var param = notify.params[i];
  701. code += genIndent(indent + 1) + 'msg.' + param.name + ' = ' + param.name + '\n';
  702. }
  703. code += genIndent(indent + 1) + 'local input = ' + firstLowerCase(classInfo.name) + '_pb.' + notify.requestType + '()\n';
  704. code += genIndent(indent + 1) + 'protobuf.FromMessage(input,msg)\n';
  705. //code += genIndent(indent + 1) + 'local input = {}\n';
  706. }
  707. //for(var i in notify.params){
  708. // var param = notify.params[i];
  709. // code += genIndent(indent+1)+'input.'+ param.name +' = '+ param.name+'\n';
  710. //}
  711. if (notify.params.length == 0) {
  712. code += genIndent(indent + 1) + 'Socket.Notify("' + notify.route + '", input)\n';
  713. }
  714. else {
  715. code += genIndent(indent + 1) + 'Socket.Notify("' + notify.route + '",ZZBase64.encode(input:SerializeToString()))\n';
  716. }
  717. code += genLuaMethodEnd(indent);
  718. return code;
  719. }
  720. function genLuaEvent(indent, classInfo, event) {
  721. var code = '';
  722. code += genLuaMethodBegin(indent, fullLuaName(classInfo.name) + '.' + event.type, [{ name: 'cb' }]);
  723. code += genIndent(indent + 1) + 'Socket.On("' + event.route + '", function(stream) \n';
  724. code += genIndent(indent + 2) + 'stream = ZZBase64.decode(stream) \n';
  725. code += genIndent(indent + 2) + 'local res = ' + firstLowerCase(event.handler) + '_pb.' + event.requestType + '() \n';
  726. code += genIndent(indent + 2) + 'res:ParseFromString(stream) \n';
  727. code += genIndent(indent + 2) + 'if(res.s2c_code == 200) then \n';
  728. code += genIndent(indent + 3) + 'Pomelo.' + classInfo.name + '.last' + event.requestType + ' = res\n';
  729. // code += genIndent(indent+3)+'Pomelo.MasteryHandler.lastUpqualityResponse = res \n';
  730. code += genIndent(indent + 3) + 'Socket.OnRequestEnd("' + event.route + '", true) \n';
  731. code += genIndent(indent + 3) + 'cb(nil,res) \n';
  732. code += genIndent(indent + 2) + 'else \n';
  733. code += genIndent(indent + 3) + 'local ex = {} \n';
  734. code += genIndent(indent + 3) + 'if(res.s2c_code) then \n';
  735. code += genIndent(indent + 4) + 'ex.Code = res.s2c_code \n';
  736. code += genIndent(indent + 4) + 'ex.Message = res.s2c_msg \n';
  737. code += genIndent(indent + 3) + 'else \n';
  738. code += genIndent(indent + 4) + 'ex.Code = 501 \n';
  739. code += genIndent(indent + 4) + 'ex.Message = "[LuaXmdsNetClient] ' + event.route + ' decode error!!" \n';
  740. code += genIndent(indent + 3) + 'end \n';
  741. code += genIndent(indent + 3) + 'Socket.OnRequestEnd("' + event.route + '", false,ex.Code,ex.Message) \n';
  742. code += genIndent(indent + 3) + 'cb(ex,nil) \n';
  743. code += genIndent(indent + 2) + 'end \n';
  744. code += genIndent(indent + 1) + 'end) \n';
  745. // code += genIndent(indent+1)+'Socket.On("'+ event.route + '", cb) \n';
  746. code += genLuaMethodEnd(indent);
  747. return code;
  748. }
  749. function genLuaClass(indent, classInfo) {
  750. var code = '';
  751. code += '--------------------------------' + classInfo.name + '-------------------------------\n';
  752. code += 'Pomelo.' + classInfo.name + ' = {}\n';
  753. code += genSpaceLine();
  754. //生成request
  755. for (var i in classInfo.requests) {
  756. var request = classInfo.requests[i];
  757. code += genLuaRequest(indent, classInfo, request);
  758. code += genSpaceLine();
  759. }
  760. //生成notify
  761. for (var i in classInfo.notifies) {
  762. var notify = classInfo.notifies[i];
  763. code += genLuaNotify(indent, classInfo, notify);
  764. code += genSpaceLine();
  765. }
  766. //生成event
  767. for (var i in classInfo.events) {
  768. var event = classInfo.events[i];
  769. code += genLuaEvent(indent, classInfo, event);
  770. code += genSpaceLine();
  771. }
  772. return code;
  773. }
  774. //生成文件头注释
  775. function genLuaComment() {
  776. var code = '-------------------------------------------------\n';
  777. code += '-- 本文件由代码生成器自动生成,\n';
  778. code += '-- 千万不要修改本文件的任何代码,\n';
  779. code += '-- 修改的的任何代码都会被覆盖掉!\n';
  780. code += '----------------------------------------------------\n';
  781. code += genSpaceLine();
  782. return code;
  783. }
  784. function genLuaFile(classInfos) {
  785. var code = '';
  786. code += genLuaComment();
  787. code += 'local Socket = require "' + argv.pathLua + '.Lua' + classInfos[0].socket + '"\n';
  788. //code += 'local cjson = require "cjson"\n';
  789. code += 'require "base64"\n';
  790. if (classInfos[0].type === 'handler') {
  791. code += 'require "' + firstLowerCase(classInfos[0].name) + '_pb"\n';
  792. }
  793. code += genSpaceLine();
  794. code += '--------------------------------Pomelo-------------------------------\n';
  795. code += 'Pomelo = Pomelo or {}\n';
  796. code += genSpaceLine();
  797. for (var i in classInfos) {
  798. code += genLuaClass(0, classInfos[i]);
  799. code += genSpaceLine();
  800. code += genSpaceLine();
  801. }
  802. code += '--------------------------------Pomelo-------------------------------\n';
  803. code += 'return Pomelo\n';
  804. return code;
  805. }
  806. function genRequire() {
  807. var code = '';
  808. for (var keySocket in sockets) {
  809. code += 'require "' + argv.pathLua + '.' + sockets[keySocket].name + '"\n';
  810. }
  811. for (var keyHandler in handlers) {
  812. if (isHandler(handlers[keyHandler].name)) {
  813. code += 'require "' + argv.pathLua + '.' + firstUpperCase(handlers[keyHandler].name) + '"\n';
  814. }
  815. }
  816. return code;
  817. }
  818. //socket文件
  819. for (var keySocket in sockets) {
  820. writeFile(argv.outputLua, sockets[keySocket].name + '.lua', genLuaFile([sockets[keySocket]]));
  821. }
  822. //handler文件
  823. for (var keyHandler in handlers) {
  824. var fileName = handlers[keyHandler].name;
  825. if (isHandler(fileName)) {
  826. writeFile(argv.outputLua, firstUpperCase(fileName) + '.lua', genLuaFile([handlers[keyHandler]]));
  827. }
  828. }
  829. writeFile(argv.outputLua, 'Pomelo.lua', genRequire());
  830. /*--------------------------------------------js代码生成--------------------------------------------------------*/
  831. function genJsMethodBegin(indent, className, method, isAsync) {
  832. var code = genIndent(indent) + className + '.prototype.' + method.type + ' = ';
  833. if (isAsync) {
  834. code += 'async(';
  835. }
  836. code += 'function(';
  837. if (method.params !== undefined) {
  838. for (var i in method.params) {
  839. var param = method.params[i];
  840. code += param.name;
  841. code += ',';
  842. }
  843. if (code[code.length - 1] === ',') {
  844. code = code.substring(0, code.length - 1);
  845. }
  846. }
  847. code += '){\n';
  848. return code;
  849. }
  850. function genJsMethodEnd(indent, isAsync) {
  851. var code = '';
  852. code += genIndent(indent) + '}';
  853. if (isAsync) {
  854. code += ')';
  855. }
  856. code += ';\n';
  857. return code;
  858. }
  859. function genJsRequest(indent, classInfo, request) {
  860. var code = '';
  861. code += genJsMethodBegin(indent, classInfo.name, request, true);
  862. code += genIndent(indent + 1) + 'return await(this.socket.requestAsync(\'' + request.route + '\',{';
  863. for (var i in request.params) {
  864. var param = request.params[i];
  865. code += param.name + ':' + param.name;
  866. if (i < request.params.length - 1) {
  867. code += ',';
  868. }
  869. }
  870. code += '}));\n';
  871. code += genJsMethodEnd(indent, true);
  872. return code;
  873. }
  874. function genJsNotify(indent, classInfo, notify) {
  875. var code = '';
  876. code += genJsMethodBegin(indent, classInfo.name, notify, false);
  877. code += genIndent(indent + 1) + 'return this.socket.notify(\'' + notify.route + '\',{';
  878. for (var i in notify.params) {
  879. var param = notify.params[i];
  880. code += param.name + ':' + param.name;
  881. if (i < notify.params.length - 1) {
  882. code += ',';
  883. }
  884. }
  885. code += '});\n';
  886. code += genJsMethodEnd(indent, false);
  887. return code;
  888. }
  889. function genJsEvent(indent, classInfo, event) {
  890. var code = '';
  891. code += genIndent(indent) + classInfo.name + '.prototype.on' + firstUpperCase(event.type) + ' = function(cb){\n';
  892. if (isHandler(classInfo.name)) {
  893. code += genIndent(indent + 1) + 'this.socket.on(\'' + event.route + '\',cb);\n';
  894. }
  895. else {
  896. code += genIndent(indent + 1) + 'this.on(\'' + event.route + '\',cb);\n';
  897. }
  898. code += genIndent(indent) + '}';
  899. return code;
  900. }
  901. function genJsConstructor(indent, classInfo) {
  902. var code = '';
  903. if (classInfo.type == 'socket') {
  904. code += genIndent(indent) + 'var ' + classInfo.name + ' = function(protoPath){\n';
  905. code += genIndent(indent + 1) + 'Socket.call(this,protoPath);\n';
  906. for (var i in classInfo.fields) {
  907. var name = classInfo.fields[i].type;
  908. if (isHandler(name)) {
  909. code += genIndent(indent + 1) + 'this.' + firstLowerCase(name) + ' = new ' + name + '(this);\n';
  910. }
  911. }
  912. }
  913. else if (classInfo.type == 'handler') {
  914. code += genIndent(indent) + 'var ' + classInfo.name + ' = function(socket){\n';
  915. code += genIndent(indent + 1) + 'this.socket = socket;\n';
  916. }
  917. code += genIndent(indent) + '}\n';
  918. return code;
  919. }
  920. function genJsClass(indent, classInfo) {
  921. var code = '';
  922. //handlers
  923. if (classInfo.type == 'socket') {
  924. for (var i in classInfo.fields) {
  925. var name = classInfo.fields[i].type;
  926. if (isHandler(name)) {
  927. code += genIndent(indent) + 'var ' + firstUpperCase(name) + ' = require(\'./' + firstLowerCase(name) + '\');\n';
  928. }
  929. }
  930. }
  931. //构造函数
  932. code += genSpaceLine();
  933. code += genJsConstructor(indent, classInfo);
  934. code += genSpaceLine();
  935. if (classInfo.type == 'socket') {
  936. code += genSpaceLine();
  937. code += genIndent(indent) + 'util.inherits(' + firstUpperCase(classInfo.name) + ', Socket);\n';
  938. code += genSpaceLine();
  939. }
  940. //生成request
  941. for (var i in classInfo.requests) {
  942. var request = classInfo.requests[i];
  943. code += genJsRequest(indent, classInfo, request);
  944. code += genSpaceLine();
  945. }
  946. //生成notify
  947. for (var i in classInfo.notifies) {
  948. var notify = classInfo.notifies[i];
  949. code += genJsNotify(indent, classInfo, notify);
  950. code += genSpaceLine();
  951. }
  952. //生成event
  953. for (var i in classInfo.events) {
  954. var event = classInfo.events[i];
  955. code += genSpaceLine();
  956. code += genJsEvent(indent, classInfo, event);
  957. code += genSpaceLine();
  958. }
  959. return code;
  960. }
  961. //生成文件头注释
  962. function genJsComment() {
  963. var code = '/*-----------------------------------------------\n';
  964. code += ' *本文件由代码生成器自动生成,\n';
  965. code += ' *千万不要修改本文件的任何代码,\n';
  966. code += ' *修改的的任何代码都会被覆盖掉!\n';
  967. code += ' --------------------------------------------------*/\n';
  968. code += genSpaceLine();
  969. return code;
  970. }
  971. function genJsFile(classInfo) {
  972. var code = '';
  973. code += genJsComment();
  974. if (classInfo.type == 'socket') {
  975. code += 'var util = require(\'util\');\n';
  976. code += 'var Socket = require(\'Xmds-csharp\').Socket;\n';
  977. }
  978. else if (classInfo.type == 'handler') {
  979. code += 'var async = require(\'asyncawait/async\');\n';
  980. code += 'var await = require(\'asyncawait/await\');\n';
  981. }
  982. code += genSpaceLine();
  983. code += genJsClass(0, classInfo);
  984. code += genSpaceLine();
  985. code += 'module.exports = ' + firstUpperCase(classInfo.name) + ';\n';
  986. return code;
  987. }
  988. if (!!argv.outputJs) {
  989. //socket文件
  990. for (var keySocket in sockets) {
  991. writeFile(argv.outputJs, sockets[keySocket].name + '.js', genJsFile(sockets[keySocket]));
  992. }
  993. //handler文件
  994. for (var keyHandler in handlers) {
  995. var fileName = handlers[keyHandler].name;
  996. if (isHandler(fileName)) {
  997. writeFile(argv.outputJs, firstLowerCase(fileName) + '.js', genJsFile(handlers[keyHandler]));
  998. }
  999. }
  1000. }